fix nan with payload parsing and safely handle out of range type indecies

This commit is contained in:
Ilya Rezvov
2021-04-07 22:38:34 -07:00
parent fa1d9a7bd1
commit 53bdf096a4
2 changed files with 36 additions and 7 deletions
+29 -6
View File
@@ -14,9 +14,9 @@ import qualified Data.ByteString.Lazy as LBS
import qualified Data.Char as Char
import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8
import Control.Monad (when)
import Numeric.IEEE (infinity, nan)
import Numeric.IEEE (infinity, nan, nanWithPayload)
import Language.Wasm.FloatUtils (makeNaN, doubleToFloat)
import Data.Word (Word8)
import Data.Word (Word8, Word64)
import Data.List (isPrefixOf)
import Text.Read (readEither)
@@ -62,8 +62,8 @@ tokens :-
<0> "nan" { constToken $ TFloatLit $ BinRep (abs nan) }
<0> "+nan" { constToken $ TFloatLit $ BinRep (abs nan) }
<0> "-nan" { constToken $ TFloatLit $ BinRep nan }
<0> "nan:canonical" { constToken $ TFloatLit $ BinRep nan }
<0> "nan:arithmetic" { constToken $ TFloatLit $ BinRep nan }
<0> "nan:canonical" { constToken $ TFloatLit $ NanRep Canonical }
<0> "nan:arithmetic" { constToken $ TFloatLit $ NanRep Arithmetic }
<0> $sign? @nanhex { parseNanSigned }
<0> "inf" { constToken $ TFloatLit $ BinRep inf }
<0> "+inf" { constToken $ TFloatLit $ BinRep inf }
@@ -131,9 +131,13 @@ parseHexalSignedInt = token $ \(pos, _, s, _) len ->
parseNanSigned :: AlexAction Lexeme
parseNanSigned = token $ \(pos, _, s, _) len ->
let (sign, slen) = parseSign s in
let (sign, slen) = case LBSUtf8.decode s of
Just ('-', _) -> (False, 1)
Just ('+', _) -> (True, 1)
otherwise -> (True, 0)
in
let num = readHexFromPrefix (len - 6 - slen) $ LBSUtf8.drop (6 + slen) s in
Lexeme (Just pos) $ TFloatLit $ BinRep $ sign $ makeNaN $ fromIntegral num
Lexeme (Just pos) $ TFloatLit $ NanRep $ NanHex sign $ fromIntegral num
parseDecimalSignedInt :: AlexAction Lexeme
parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
@@ -218,11 +222,23 @@ asFloat :: FloatRep -> Either String Float
asFloat (BinRep d) = Right $ doubleToFloat d
asFloat (HexRep s) = doubleToFloat <$> readHexFloat 128 "ffffff" s
asFloat (DecRep s) = readDecFloat s
asFloat (NanRep Canonical) = Right nan
asFloat (NanRep Arithmetic) = Right nan
asFloat (NanRep (NanHex isPos payload)) =
if payload >= 1 && payload < 2 ^ 23
then return $ doubleToFloat $ (if isPos then id else negate) $ makeNaN payload
else Left "constant out of range"
asDouble :: FloatRep -> Either String Double
asDouble (BinRep d) = Right d
asDouble (HexRep s) = readHexFloat 1024 "fffffffffffff8" s
asDouble (DecRep s) = readDecDouble s
asDouble (NanRep Canonical) = Right nan
asDouble (NanRep Arithmetic) = Right nan
asDouble (NanRep (NanHex isPos payload)) =
if payload >= 1 && payload < 2 ^ 52
then return $ (if isPos then id else negate) $ makeNaN payload
else Left "constant out of range"
startBlockComment :: AlexAction Lexeme
startBlockComment _inp _len = do
@@ -300,6 +316,13 @@ data FloatRep
= BinRep Double
| DecRep String
| HexRep String
| NanRep NaN
deriving (Show, Eq)
data NaN
= Canonical
| Arithmetic
| NanHex Bool Word64
deriving (Show, Eq)
data Token = TKeyword LBS.ByteString
+7 -1
View File
@@ -1461,6 +1461,11 @@ desugarize fields = do
else (TypeDef Nothing funcType) : defs
matchTypeUse defs _ = defs
nth :: Natural -> [a] -> Maybe a
nth 0 (x : xs) = Just x
nth n (_ : xs) = nth (n - 1) xs
nth _ _ = Nothing
getTypeIndex :: [TypeDef] -> TypeUse -> Maybe Natural
getTypeIndex defs (AnonimousTypeUse funcType) =
fromIntegral <$> findIndex (matchTypeFunc funcType) defs
@@ -1471,7 +1476,8 @@ desugarize fields = do
getTypeIndex defs (IndexedTypeUse (Named ident) Nothing) =
fromIntegral <$> findIndex (\(TypeDef i _) -> i == Just ident) defs
getTypeIndex defs (IndexedTypeUse (Index n) (Just funcType)) = do
guard $ matchTypeFunc funcType $ defs !! fromIntegral n
def <- nth n defs
guard $ matchTypeFunc funcType def
return n
getTypeIndex defs (IndexedTypeUse (Index n) Nothing) = return n