fix nan with payload parsing and safely handle out of range type indecies
This commit is contained in:
@@ -14,9 +14,9 @@ import qualified Data.ByteString.Lazy as LBS
|
|||||||
import qualified Data.Char as Char
|
import qualified Data.Char as Char
|
||||||
import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8
|
import qualified Data.ByteString.Lazy.UTF8 as LBSUtf8
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
import Numeric.IEEE (infinity, nan)
|
import Numeric.IEEE (infinity, nan, nanWithPayload)
|
||||||
import Language.Wasm.FloatUtils (makeNaN, doubleToFloat)
|
import Language.Wasm.FloatUtils (makeNaN, doubleToFloat)
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8, Word64)
|
||||||
import Data.List (isPrefixOf)
|
import Data.List (isPrefixOf)
|
||||||
import Text.Read (readEither)
|
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 (abs nan) }
|
<0> "+nan" { constToken $ TFloatLit $ BinRep (abs nan) }
|
||||||
<0> "-nan" { constToken $ TFloatLit $ BinRep nan }
|
<0> "-nan" { constToken $ TFloatLit $ BinRep nan }
|
||||||
<0> "nan:canonical" { constToken $ TFloatLit $ BinRep nan }
|
<0> "nan:canonical" { constToken $ TFloatLit $ NanRep Canonical }
|
||||||
<0> "nan:arithmetic" { constToken $ TFloatLit $ BinRep nan }
|
<0> "nan:arithmetic" { constToken $ TFloatLit $ NanRep Arithmetic }
|
||||||
<0> $sign? @nanhex { parseNanSigned }
|
<0> $sign? @nanhex { parseNanSigned }
|
||||||
<0> "inf" { constToken $ TFloatLit $ BinRep inf }
|
<0> "inf" { constToken $ TFloatLit $ BinRep inf }
|
||||||
<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 :: AlexAction Lexeme
|
||||||
parseNanSigned = token $ \(pos, _, s, _) len ->
|
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
|
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 :: AlexAction Lexeme
|
||||||
parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
|
parseDecimalSignedInt = token $ \(pos, _, s, _) len ->
|
||||||
@@ -218,11 +222,23 @@ asFloat :: FloatRep -> Either String Float
|
|||||||
asFloat (BinRep d) = Right $ doubleToFloat d
|
asFloat (BinRep d) = Right $ doubleToFloat d
|
||||||
asFloat (HexRep s) = doubleToFloat <$> readHexFloat 128 "ffffff" s
|
asFloat (HexRep s) = doubleToFloat <$> readHexFloat 128 "ffffff" s
|
||||||
asFloat (DecRep s) = readDecFloat 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 :: FloatRep -> Either String Double
|
||||||
asDouble (BinRep d) = Right d
|
asDouble (BinRep d) = Right d
|
||||||
asDouble (HexRep s) = readHexFloat 1024 "fffffffffffff8" s
|
asDouble (HexRep s) = readHexFloat 1024 "fffffffffffff8" s
|
||||||
asDouble (DecRep s) = readDecDouble 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 :: AlexAction Lexeme
|
||||||
startBlockComment _inp _len = do
|
startBlockComment _inp _len = do
|
||||||
@@ -300,6 +316,13 @@ data FloatRep
|
|||||||
= BinRep Double
|
= BinRep Double
|
||||||
| DecRep String
|
| DecRep String
|
||||||
| HexRep String
|
| HexRep String
|
||||||
|
| NanRep NaN
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
data NaN
|
||||||
|
= Canonical
|
||||||
|
| Arithmetic
|
||||||
|
| NanHex Bool Word64
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Token = TKeyword LBS.ByteString
|
data Token = TKeyword LBS.ByteString
|
||||||
|
|||||||
@@ -1461,6 +1461,11 @@ desugarize fields = do
|
|||||||
else (TypeDef Nothing funcType) : defs
|
else (TypeDef Nothing funcType) : defs
|
||||||
matchTypeUse defs _ = 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 :: [TypeDef] -> TypeUse -> Maybe Natural
|
||||||
getTypeIndex defs (AnonimousTypeUse funcType) =
|
getTypeIndex defs (AnonimousTypeUse funcType) =
|
||||||
fromIntegral <$> findIndex (matchTypeFunc funcType) defs
|
fromIntegral <$> findIndex (matchTypeFunc funcType) defs
|
||||||
@@ -1471,7 +1476,8 @@ desugarize fields = do
|
|||||||
getTypeIndex defs (IndexedTypeUse (Named ident) Nothing) =
|
getTypeIndex defs (IndexedTypeUse (Named ident) Nothing) =
|
||||||
fromIntegral <$> findIndex (\(TypeDef i _) -> i == Just ident) defs
|
fromIntegral <$> findIndex (\(TypeDef i _) -> i == Just ident) defs
|
||||||
getTypeIndex defs (IndexedTypeUse (Index n) (Just funcType)) = do
|
getTypeIndex defs (IndexedTypeUse (Index n) (Just funcType)) = do
|
||||||
guard $ matchTypeFunc funcType $ defs !! fromIntegral n
|
def <- nth n defs
|
||||||
|
guard $ matchTypeFunc funcType def
|
||||||
return n
|
return n
|
||||||
getTypeIndex defs (IndexedTypeUse (Index n) Nothing) = return n
|
getTypeIndex defs (IndexedTypeUse (Index n) Nothing) = return n
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user