forbid special nan values for non-script contexts
This commit is contained in:
@@ -5,6 +5,8 @@ module Language.Wasm.Lexer (
|
|||||||
Lexeme(..),
|
Lexeme(..),
|
||||||
Token(..),
|
Token(..),
|
||||||
AlexPosn(..),
|
AlexPosn(..),
|
||||||
|
FloatRep(..),
|
||||||
|
NaN(..),
|
||||||
scanner,
|
scanner,
|
||||||
asFloat,
|
asFloat,
|
||||||
asDouble,
|
asDouble,
|
||||||
@@ -22,6 +24,8 @@ import Data.List (isPrefixOf)
|
|||||||
import Text.Read (readEither)
|
import Text.Read (readEither)
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
import Numeric (showHex)
|
import Numeric (showHex)
|
||||||
|
import Control.DeepSeq (NFData)
|
||||||
|
import GHC.Generics (Generic)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+56
-42
@@ -93,6 +93,8 @@ import Language.Wasm.Lexer (
|
|||||||
),
|
),
|
||||||
Lexeme(..),
|
Lexeme(..),
|
||||||
AlexPosn(..),
|
AlexPosn(..),
|
||||||
|
FloatRep(..),
|
||||||
|
NaN(..),
|
||||||
asFloat,
|
asFloat,
|
||||||
asDouble,
|
asDouble,
|
||||||
doubleFromInteger
|
doubleFromInteger
|
||||||
@@ -407,23 +409,23 @@ int64 :: { Integer }
|
|||||||
else Left ("Int literal value is out of signed int64 boundaries: " ++ show $1)
|
else Left ("Int literal value is out of signed int64 boundaries: " ++ show $1)
|
||||||
}
|
}
|
||||||
|
|
||||||
float32 :: { Float }
|
float32 :: { FloatRep }
|
||||||
: int {%
|
: int {%
|
||||||
let maxInt = 340282356779733623858607532500980858880 in
|
let maxInt = 340282356779733623858607532500980858880 in
|
||||||
if $1 <= maxInt && $1 >= -maxInt
|
if $1 <= maxInt && $1 >= -maxInt
|
||||||
then return $ fromIntegral $1
|
then return $ BinRep $ fromIntegral $1
|
||||||
else Left "constant out of range"
|
else Left "constant out of range"
|
||||||
}
|
}
|
||||||
| f64 {% asFloat $1 }
|
| f64 { $1 }
|
||||||
|
|
||||||
float64 :: { Double }
|
float64 :: { FloatRep }
|
||||||
: int {%
|
: int {%
|
||||||
let maxInt = round (maxFinite :: Double) in
|
let maxInt = round (maxFinite :: Double) in
|
||||||
if $1 <= maxInt && $1 >= -maxInt
|
if $1 <= maxInt && $1 >= -maxInt
|
||||||
then doubleFromInteger $1
|
then fmap BinRep $ doubleFromInteger $1
|
||||||
else Left "constant out of range"
|
else Left "constant out of range"
|
||||||
}
|
}
|
||||||
| f64 {% asDouble $1 }
|
| f64 { $1 }
|
||||||
|
|
||||||
plaininstr :: { PlainInstr }
|
plaininstr :: { PlainInstr }
|
||||||
-- control instructions
|
-- control instructions
|
||||||
@@ -1040,11 +1042,15 @@ module1 :: { ModuleDef }
|
|||||||
| 'module' opt(ident) list(modulefield) ')' {% RawModDef $2 `fmap` (desugarize $ concat $3) }
|
| 'module' opt(ident) list(modulefield) ')' {% RawModDef $2 `fmap` (desugarize $ concat $3) }
|
||||||
|
|
||||||
action1 :: { Action }
|
action1 :: { Action }
|
||||||
: 'invoke' opt(ident) string list(folded_instr) ')' { Invoke $2 $3 (map (map constInstructionToValue) $4) }
|
: 'invoke' opt(ident) string list(folded_instr) ')' {%
|
||||||
|
fmap (Invoke $2 $3) $ (mapM (mapM constInstructionToValue) $4)
|
||||||
|
}
|
||||||
| 'get' opt(ident) string ')' { Get $2 $3 }
|
| 'get' opt(ident) string ')' { Get $2 $3 }
|
||||||
|
|
||||||
assertion1 :: { (Maybe AlexPosn, Assertion) }
|
assertion1 :: { (Maybe AlexPosn, Assertion) }
|
||||||
: 'assert_return' '(' action1 list(folded_instr) ')' { ($1, AssertReturn $3 (map (map constInstructionToValue) $4)) }
|
: 'assert_return' '(' action1 list(folded_instr) ')' {%
|
||||||
|
fmap ((\a -> ($1, a)) . AssertReturn $3) $ (mapM (mapM constInstructionToValue) $4)
|
||||||
|
}
|
||||||
| 'assert_return_canonical_nan' '(' action1 ')' { ($1, AssertReturnCanonicalNaN $3) }
|
| 'assert_return_canonical_nan' '(' action1 ')' { ($1, AssertReturnCanonicalNaN $3) }
|
||||||
| 'assert_return_arithmetic_nan' '(' action1 ')' { ($1, AssertReturnArithmeticNaN $3) }
|
| 'assert_return_arithmetic_nan' '(' action1 ')' { ($1, AssertReturnArithmeticNaN $3) }
|
||||||
| 'assert_trap' '(' assertion_trap string ')' { ($1, AssertTrap $3 $4) }
|
| 'assert_trap' '(' assertion_trap string ')' { ($1, AssertTrap $3 $4) }
|
||||||
@@ -1160,7 +1166,7 @@ integerToWord64 i
|
|||||||
| i < 0 && i >= -(2 ^ 63) = 0xFFFFFFFFFFFFFFFF - (fromIntegral (abs i)) + 1
|
| i < 0 && i >= -(2 ^ 63) = 0xFFFFFFFFFFFFFFFF - (fromIntegral (abs i)) + 1
|
||||||
| otherwise = error "I64 is out of bounds."
|
| otherwise = error "I64 is out of bounds."
|
||||||
|
|
||||||
data FuncType = FuncType { params :: [ParamType], results :: [ValueType] } deriving (Show, Eq, Generic, NFData)
|
data FuncType = FuncType { params :: [ParamType], results :: [ValueType] } deriving (Show, Eq)
|
||||||
|
|
||||||
emptyFuncType :: FuncType
|
emptyFuncType :: FuncType
|
||||||
emptyFuncType = FuncType [] []
|
emptyFuncType = FuncType [] []
|
||||||
@@ -1168,11 +1174,11 @@ emptyFuncType = FuncType [] []
|
|||||||
data ParamType = ParamType {
|
data ParamType = ParamType {
|
||||||
ident :: Maybe Ident,
|
ident :: Maybe Ident,
|
||||||
paramType :: ValueType
|
paramType :: ValueType
|
||||||
} deriving (Show, Eq, Generic, NFData)
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
newtype Ident = Ident TL.Text deriving (Show, Eq, Generic, NFData)
|
newtype Ident = Ident TL.Text deriving (Show, Eq)
|
||||||
|
|
||||||
data Index = Named Ident | Index Natural deriving (Show, Eq, Generic, NFData)
|
data Index = Named Ident | Index Natural deriving (Show, Eq)
|
||||||
|
|
||||||
type LabelIndex = Index
|
type LabelIndex = Index
|
||||||
type FuncIndex = Index
|
type FuncIndex = Index
|
||||||
@@ -1245,8 +1251,8 @@ data PlainInstr =
|
|||||||
-- Numeric instructions
|
-- Numeric instructions
|
||||||
| I32Const Integer
|
| I32Const Integer
|
||||||
| I64Const Integer
|
| I64Const Integer
|
||||||
| F32Const Float
|
| F32Const FloatRep
|
||||||
| F64Const Double
|
| F64Const FloatRep
|
||||||
| IUnOp BitSize IUnOp
|
| IUnOp BitSize IUnOp
|
||||||
| IBinOp BitSize IBinOp
|
| IBinOp BitSize IBinOp
|
||||||
| I32Eqz
|
| I32Eqz
|
||||||
@@ -1268,14 +1274,14 @@ data PlainInstr =
|
|||||||
| F64PromoteF32
|
| F64PromoteF32
|
||||||
| IReinterpretF BitSize
|
| IReinterpretF BitSize
|
||||||
| FReinterpretI BitSize
|
| FReinterpretI BitSize
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data TypeDef = TypeDef (Maybe Ident) FuncType deriving (Show, Eq, Generic, NFData)
|
data TypeDef = TypeDef (Maybe Ident) FuncType deriving (Show, Eq)
|
||||||
|
|
||||||
data TypeUse =
|
data TypeUse =
|
||||||
IndexedTypeUse TypeIndex (Maybe FuncType)
|
IndexedTypeUse TypeIndex (Maybe FuncType)
|
||||||
| AnonimousTypeUse FuncType
|
| AnonimousTypeUse FuncType
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
emptyTypeUse = AnonimousTypeUse emptyFuncType
|
emptyTypeUse = AnonimousTypeUse emptyFuncType
|
||||||
|
|
||||||
@@ -1297,26 +1303,26 @@ data Instruction =
|
|||||||
trueBranch :: [Instruction],
|
trueBranch :: [Instruction],
|
||||||
falseBranch :: [Instruction]
|
falseBranch :: [Instruction]
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Import = Import {
|
data Import = Import {
|
||||||
reExportAs :: [TL.Text],
|
reExportAs :: [TL.Text],
|
||||||
sourceModule :: TL.Text,
|
sourceModule :: TL.Text,
|
||||||
name :: TL.Text,
|
name :: TL.Text,
|
||||||
desc :: ImportDesc
|
desc :: ImportDesc
|
||||||
} deriving (Show, Eq, Generic, NFData)
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
data ImportDesc =
|
data ImportDesc =
|
||||||
ImportFunc (Maybe Ident) TypeUse
|
ImportFunc (Maybe Ident) TypeUse
|
||||||
| ImportTable (Maybe Ident) TableType
|
| ImportTable (Maybe Ident) TableType
|
||||||
| ImportMemory (Maybe Ident) Limit
|
| ImportMemory (Maybe Ident) Limit
|
||||||
| ImportGlobal (Maybe Ident) GlobalType
|
| ImportGlobal (Maybe Ident) GlobalType
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data LocalType = LocalType {
|
data LocalType = LocalType {
|
||||||
ident :: Maybe Ident,
|
ident :: Maybe Ident,
|
||||||
localType :: ValueType
|
localType :: ValueType
|
||||||
} deriving (Show, Eq, Generic, NFData)
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
data Function = Function {
|
data Function = Function {
|
||||||
exportFuncAs :: [TL.Text],
|
exportFuncAs :: [TL.Text],
|
||||||
@@ -1325,7 +1331,7 @@ data Function = Function {
|
|||||||
locals :: [LocalType],
|
locals :: [LocalType],
|
||||||
body :: [Instruction]
|
body :: [Instruction]
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
emptyFunction :: Function
|
emptyFunction :: Function
|
||||||
emptyFunction =
|
emptyFunction =
|
||||||
@@ -1343,32 +1349,32 @@ data Global = Global {
|
|||||||
globalType :: GlobalType,
|
globalType :: GlobalType,
|
||||||
initializer :: [Instruction]
|
initializer :: [Instruction]
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Memory = Memory [TL.Text] (Maybe Ident) Limit deriving (Show, Eq, Generic, NFData)
|
data Memory = Memory [TL.Text] (Maybe Ident) Limit deriving (Show, Eq)
|
||||||
|
|
||||||
data Table = Table [TL.Text] (Maybe Ident) TableType deriving (Show, Eq, Generic, NFData)
|
data Table = Table [TL.Text] (Maybe Ident) TableType deriving (Show, Eq)
|
||||||
|
|
||||||
data ExportDesc =
|
data ExportDesc =
|
||||||
ExportFunc FuncIndex
|
ExportFunc FuncIndex
|
||||||
| ExportTable TableIndex
|
| ExportTable TableIndex
|
||||||
| ExportMemory MemoryIndex
|
| ExportMemory MemoryIndex
|
||||||
| ExportGlobal GlobalIndex
|
| ExportGlobal GlobalIndex
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data Export = Export {
|
data Export = Export {
|
||||||
name :: TL.Text,
|
name :: TL.Text,
|
||||||
desc :: ExportDesc
|
desc :: ExportDesc
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data StartFunction = StartFunction FuncIndex deriving (Show, Eq, Generic, NFData)
|
data StartFunction = StartFunction FuncIndex deriving (Show, Eq)
|
||||||
|
|
||||||
data ElemMode
|
data ElemMode
|
||||||
= Passive
|
= Passive
|
||||||
| Active TableIndex [Instruction]
|
| Active TableIndex [Instruction]
|
||||||
| Declarative
|
| Declarative
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data ElemSegment = ElemSegment {
|
data ElemSegment = ElemSegment {
|
||||||
ident :: Maybe Ident,
|
ident :: Maybe Ident,
|
||||||
@@ -1376,14 +1382,14 @@ data ElemSegment = ElemSegment {
|
|||||||
mode :: ElemMode,
|
mode :: ElemMode,
|
||||||
elements :: [[Instruction]]
|
elements :: [[Instruction]]
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data DataSegment = DataSegment {
|
data DataSegment = DataSegment {
|
||||||
memIndex :: MemoryIndex,
|
memIndex :: MemoryIndex,
|
||||||
offset :: [Instruction],
|
offset :: [Instruction],
|
||||||
datastring :: LBS.ByteString
|
datastring :: LBS.ByteString
|
||||||
}
|
}
|
||||||
deriving (Show, Eq, Generic, NFData)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
data ModuleField =
|
data ModuleField =
|
||||||
MFType TypeDef
|
MFType TypeDef
|
||||||
@@ -1396,7 +1402,7 @@ data ModuleField =
|
|||||||
| MFStart StartFunction
|
| MFStart StartFunction
|
||||||
| MFElem ElemSegment
|
| MFElem ElemSegment
|
||||||
| MFData DataSegment
|
| MFData DataSegment
|
||||||
deriving(Show, Eq, Generic, NFData)
|
deriving(Show, Eq)
|
||||||
|
|
||||||
happyError (Lexeme _ EOF : []) = Left $ "Error occuried during parsing phase at the end of file"
|
happyError (Lexeme _ EOF : []) = Left $ "Error occuried during parsing phase at the end of file"
|
||||||
happyError (Lexeme Nothing tok : tokens) = Left $ "Error occuried during parsing phase at the end of file"
|
happyError (Lexeme Nothing tok : tokens) = Left $ "Error occuried during parsing phase at the end of file"
|
||||||
@@ -1469,14 +1475,14 @@ data FunCtx = FunCtx {
|
|||||||
ctxParams :: [ParamType]
|
ctxParams :: [ParamType]
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
constInstructionToValue :: Instruction -> S.Instruction Natural
|
constInstructionToValue :: Instruction -> Either String (S.Instruction Natural)
|
||||||
constInstructionToValue (PlainInstr (I32Const v)) = S.I32Const $ integerToWord32 v
|
constInstructionToValue (PlainInstr (I32Const v)) = return $ S.I32Const $ integerToWord32 v
|
||||||
constInstructionToValue (PlainInstr (F32Const v)) = S.F32Const v
|
constInstructionToValue (PlainInstr (F32Const v)) = S.F32Const <$> asFloat v
|
||||||
constInstructionToValue (PlainInstr (I64Const v)) = S.I64Const $ integerToWord64 v
|
constInstructionToValue (PlainInstr (I64Const v)) = return $ S.I64Const $ integerToWord64 v
|
||||||
constInstructionToValue (PlainInstr (F64Const v)) = S.F64Const v
|
constInstructionToValue (PlainInstr (F64Const v)) = S.F64Const <$> asDouble v
|
||||||
constInstructionToValue (PlainInstr (RefNull et)) = S.RefNull et
|
constInstructionToValue (PlainInstr (RefNull et)) = return $ S.RefNull et
|
||||||
constInstructionToValue (PlainInstr (RefExtern n)) = S.RefExtern n
|
constInstructionToValue (PlainInstr (RefExtern n)) = return $ S.RefExtern n
|
||||||
constInstructionToValue _ = error "Only const instructions supported as arguments for actions"
|
constInstructionToValue _ = Left "Only const instructions supported as arguments for actions"
|
||||||
|
|
||||||
funcIndexToExpr :: [FuncIndex] -> [[Instruction]]
|
funcIndexToExpr :: [FuncIndex] -> [[Instruction]]
|
||||||
funcIndexToExpr = map $ (:[]) . PlainInstr . RefFunc
|
funcIndexToExpr = map $ (:[]) . PlainInstr . RefFunc
|
||||||
@@ -1759,8 +1765,16 @@ desugarize fields = do
|
|||||||
Nothing -> Left "unknown elem"
|
Nothing -> Left "unknown elem"
|
||||||
synInstrToStruct _ (PlainInstr (I32Const val)) = return $ S.I32Const $ integerToWord32 val
|
synInstrToStruct _ (PlainInstr (I32Const val)) = return $ S.I32Const $ integerToWord32 val
|
||||||
synInstrToStruct _ (PlainInstr (I64Const val)) = return $ S.I64Const $ integerToWord64 val
|
synInstrToStruct _ (PlainInstr (I64Const val)) = return $ S.I64Const $ integerToWord64 val
|
||||||
synInstrToStruct _ (PlainInstr (F32Const val)) = return $ S.F32Const val
|
synInstrToStruct _ (PlainInstr (F32Const (NanRep Arithmetic))) =
|
||||||
synInstrToStruct _ (PlainInstr (F64Const val)) = return $ S.F64Const val
|
Left "arithmetic nan constant allowed only in script"
|
||||||
|
synInstrToStruct _ (PlainInstr (F32Const (NanRep Canonical))) =
|
||||||
|
Left "canonical nan constant allowed only in script"
|
||||||
|
synInstrToStruct _ (PlainInstr (F32Const rep)) = S.F32Const <$> asFloat rep
|
||||||
|
synInstrToStruct _ (PlainInstr (F64Const (NanRep Arithmetic))) =
|
||||||
|
Left "arithmetic nan constant allowed only in script"
|
||||||
|
synInstrToStruct _ (PlainInstr (F64Const (NanRep Canonical))) =
|
||||||
|
Left "canonical nan constant allowed only in script"
|
||||||
|
synInstrToStruct _ (PlainInstr (F64Const rep)) = S.F64Const <$> asDouble rep
|
||||||
synInstrToStruct _ (PlainInstr (IUnOp sz op)) = return $ S.IUnOp sz op
|
synInstrToStruct _ (PlainInstr (IUnOp sz op)) = return $ S.IUnOp sz op
|
||||||
synInstrToStruct _ (PlainInstr (IBinOp sz op)) = return $ S.IBinOp sz op
|
synInstrToStruct _ (PlainInstr (IBinOp sz op)) = return $ S.IBinOp sz op
|
||||||
synInstrToStruct _ (PlainInstr I32Eqz) = return $ S.I32Eqz
|
synInstrToStruct _ (PlainInstr I32Eqz) = return $ S.I32Eqz
|
||||||
|
|||||||
Reference in New Issue
Block a user