@@ -275,12 +275,24 @@ pub trait WasmModuleResources {
275
275
276
276
type OperatorValidatorResult < T > = result:: Result < T , & ' static str > ;
277
277
278
+ #[ derive( Copy , Clone ) ]
279
+ pub struct OperatorValidatorConfig {
280
+ pub enable_threads : bool ,
281
+ }
282
+
283
+ const DEFAULT_OPERATOR_VALIDATOR_CONFIG : OperatorValidatorConfig =
284
+ OperatorValidatorConfig { enable_threads : false } ;
285
+
278
286
struct OperatorValidator {
279
287
func_state : FuncState ,
288
+ config : OperatorValidatorConfig ,
280
289
}
281
290
282
291
impl OperatorValidator {
283
- pub fn new ( func_type : & FuncType , locals : & Vec < ( u32 , Type ) > ) -> OperatorValidator {
292
+ pub fn new ( func_type : & FuncType ,
293
+ locals : & Vec < ( u32 , Type ) > ,
294
+ config : OperatorValidatorConfig )
295
+ -> OperatorValidator {
284
296
let mut local_types = Vec :: new ( ) ;
285
297
local_types. extend_from_slice ( func_type. params . as_slice ( ) ) ;
286
298
for local in locals {
@@ -308,6 +320,7 @@ impl OperatorValidator {
308
320
stack_types : Vec :: new ( ) ,
309
321
end_function : false ,
310
322
} ,
323
+ config,
311
324
}
312
325
}
313
326
@@ -477,6 +490,13 @@ impl OperatorValidator {
477
490
Ok ( ( ) )
478
491
}
479
492
493
+ fn check_threads_enabled ( & self ) -> OperatorValidatorResult < ( ) > {
494
+ if !self . config . enable_threads {
495
+ return Err ( "threads support is not enabled" ) ;
496
+ }
497
+ Ok ( ( ) )
498
+ }
499
+
480
500
fn check_shared_memarg_wo_align ( & self ,
481
501
_: & MemoryImmediate ,
482
502
resources : & WasmModuleResources )
@@ -1022,6 +1042,7 @@ impl OperatorValidator {
1022
1042
Operator :: I32AtomicLoad { ref memarg } |
1023
1043
Operator :: I32AtomicLoad16U { ref memarg } |
1024
1044
Operator :: I32AtomicLoad8U { ref memarg } => {
1045
+ self . check_threads_enabled ( ) ?;
1025
1046
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1026
1047
self . check_operands_1 ( func_state, Type :: I32 ) ?;
1027
1048
OperatorAction :: ChangeFrameWithType ( 1 , Type :: I32 )
@@ -1030,13 +1051,15 @@ impl OperatorValidator {
1030
1051
Operator :: I64AtomicLoad32U { ref memarg } |
1031
1052
Operator :: I64AtomicLoad16U { ref memarg } |
1032
1053
Operator :: I64AtomicLoad8U { ref memarg } => {
1054
+ self . check_threads_enabled ( ) ?;
1033
1055
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1034
1056
self . check_operands_1 ( func_state, Type :: I32 ) ?;
1035
1057
OperatorAction :: ChangeFrameWithType ( 1 , Type :: I64 )
1036
1058
}
1037
1059
Operator :: I32AtomicStore { ref memarg } |
1038
1060
Operator :: I32AtomicStore16 { ref memarg } |
1039
1061
Operator :: I32AtomicStore8 { ref memarg } => {
1062
+ self . check_threads_enabled ( ) ?;
1040
1063
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1041
1064
self . check_operands_2 ( func_state, Type :: I32 , Type :: I32 ) ?;
1042
1065
OperatorAction :: ChangeFrame ( 2 )
@@ -1045,6 +1068,7 @@ impl OperatorValidator {
1045
1068
Operator :: I64AtomicStore32 { ref memarg } |
1046
1069
Operator :: I64AtomicStore16 { ref memarg } |
1047
1070
Operator :: I64AtomicStore8 { ref memarg } => {
1071
+ self . check_threads_enabled ( ) ?;
1048
1072
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1049
1073
self . check_operands_2 ( func_state, Type :: I32 , Type :: I64 ) ?;
1050
1074
OperatorAction :: ChangeFrame ( 2 )
@@ -1064,6 +1088,7 @@ impl OperatorValidator {
1064
1088
Operator :: I32AtomicRmw8UAnd { ref memarg } |
1065
1089
Operator :: I32AtomicRmw8UOr { ref memarg } |
1066
1090
Operator :: I32AtomicRmw8UXor { ref memarg } => {
1091
+ self . check_threads_enabled ( ) ?;
1067
1092
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1068
1093
self . check_operands_2 ( func_state, Type :: I32 , Type :: I32 ) ?;
1069
1094
OperatorAction :: ChangeFrameWithType ( 2 , Type :: I32 )
@@ -1088,20 +1113,23 @@ impl OperatorValidator {
1088
1113
Operator :: I64AtomicRmw8UAnd { ref memarg } |
1089
1114
Operator :: I64AtomicRmw8UOr { ref memarg } |
1090
1115
Operator :: I64AtomicRmw8UXor { ref memarg } => {
1116
+ self . check_threads_enabled ( ) ?;
1091
1117
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1092
1118
self . check_operands_2 ( func_state, Type :: I32 , Type :: I64 ) ?;
1093
1119
OperatorAction :: ChangeFrameWithType ( 2 , Type :: I64 )
1094
1120
}
1095
1121
Operator :: I32AtomicRmwXchg { ref memarg } |
1096
1122
Operator :: I32AtomicRmw16UXchg { ref memarg } |
1097
1123
Operator :: I32AtomicRmw8UXchg { ref memarg } => {
1124
+ self . check_threads_enabled ( ) ?;
1098
1125
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1099
1126
self . check_operands_2 ( func_state, Type :: I32 , Type :: I32 ) ?;
1100
1127
OperatorAction :: ChangeFrameWithType ( 2 , Type :: I32 )
1101
1128
}
1102
1129
Operator :: I32AtomicRmwCmpxchg { ref memarg } |
1103
1130
Operator :: I32AtomicRmw16UCmpxchg { ref memarg } |
1104
1131
Operator :: I32AtomicRmw8UCmpxchg { ref memarg } => {
1132
+ self . check_threads_enabled ( ) ?;
1105
1133
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1106
1134
self . check_operands ( func_state, & [ Type :: I32 , Type :: I32 , Type :: I32 ] ) ?;
1107
1135
OperatorAction :: ChangeFrameWithType ( 3 , Type :: I32 )
@@ -1110,6 +1138,7 @@ impl OperatorValidator {
1110
1138
Operator :: I64AtomicRmw32UXchg { ref memarg } |
1111
1139
Operator :: I64AtomicRmw16UXchg { ref memarg } |
1112
1140
Operator :: I64AtomicRmw8UXchg { ref memarg } => {
1141
+ self . check_threads_enabled ( ) ?;
1113
1142
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1114
1143
self . check_operands_2 ( func_state, Type :: I32 , Type :: I64 ) ?;
1115
1144
OperatorAction :: ChangeFrameWithType ( 2 , Type :: I64 )
@@ -1118,21 +1147,25 @@ impl OperatorValidator {
1118
1147
Operator :: I64AtomicRmw32UCmpxchg { ref memarg } |
1119
1148
Operator :: I64AtomicRmw16UCmpxchg { ref memarg } |
1120
1149
Operator :: I64AtomicRmw8UCmpxchg { ref memarg } => {
1150
+ self . check_threads_enabled ( ) ?;
1121
1151
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1122
1152
self . check_operands ( func_state, & [ Type :: I32 , Type :: I64 , Type :: I64 ] ) ?;
1123
1153
OperatorAction :: ChangeFrameWithType ( 3 , Type :: I64 )
1124
1154
}
1125
1155
Operator :: Wake { ref memarg } => {
1156
+ self . check_threads_enabled ( ) ?;
1126
1157
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1127
1158
self . check_operands_2 ( func_state, Type :: I32 , Type :: I32 ) ?;
1128
1159
OperatorAction :: ChangeFrameWithType ( 2 , Type :: I32 )
1129
1160
}
1130
1161
Operator :: I32Wait { ref memarg } => {
1162
+ self . check_threads_enabled ( ) ?;
1131
1163
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1132
1164
self . check_operands ( func_state, & [ Type :: I32 , Type :: I32 , Type :: I64 ] ) ?;
1133
1165
OperatorAction :: ChangeFrameWithType ( 3 , Type :: I32 )
1134
1166
}
1135
1167
Operator :: I64Wait { ref memarg } => {
1168
+ self . check_threads_enabled ( ) ?;
1136
1169
self . check_shared_memarg_wo_align ( memarg, resources) ?;
1137
1170
self . check_operands ( func_state, & [ Type :: I32 , Type :: I64 , Type :: I64 ] ) ?;
1138
1171
OperatorAction :: ChangeFrameWithType ( 3 , Type :: I32 )
@@ -1149,6 +1182,14 @@ impl OperatorValidator {
1149
1182
}
1150
1183
}
1151
1184
1185
+ #[ derive( Copy , Clone ) ]
1186
+ pub struct ValidatingParserConfig {
1187
+ pub operator_config : OperatorValidatorConfig ,
1188
+ }
1189
+
1190
+ const DEFAULT_VALIDATING_PARSER_CONFIG : ValidatingParserConfig =
1191
+ ValidatingParserConfig { operator_config : DEFAULT_OPERATOR_VALIDATOR_CONFIG } ;
1192
+
1152
1193
pub struct ValidatingParser < ' a > {
1153
1194
parser : Parser < ' a > ,
1154
1195
validation_error : Option < ParserState < ' a > > ,
@@ -1164,6 +1205,7 @@ pub struct ValidatingParser<'a> {
1164
1205
init_expression_state : Option < InitExpressionState > ,
1165
1206
exported_names : HashSet < Vec < u8 > > ,
1166
1207
current_operator_validator : Option < OperatorValidator > ,
1208
+ config : ValidatingParserConfig ,
1167
1209
}
1168
1210
1169
1211
impl < ' a > WasmModuleResources for ValidatingParser < ' a > {
@@ -1189,7 +1231,7 @@ impl<'a> WasmModuleResources for ValidatingParser<'a> {
1189
1231
}
1190
1232
1191
1233
impl < ' a > ValidatingParser < ' a > {
1192
- pub fn new ( bytes : & [ u8 ] ) -> ValidatingParser {
1234
+ pub fn new ( bytes : & [ u8 ] , config : Option < ValidatingParserConfig > ) -> ValidatingParser {
1193
1235
ValidatingParser {
1194
1236
parser : Parser :: new ( bytes) ,
1195
1237
validation_error : None ,
@@ -1205,6 +1247,7 @@ impl<'a> ValidatingParser<'a> {
1205
1247
current_operator_validator : None ,
1206
1248
init_expression_state : None ,
1207
1249
exported_names : HashSet :: new ( ) ,
1250
+ config : config. unwrap_or ( DEFAULT_VALIDATING_PARSER_CONFIG ) ,
1208
1251
}
1209
1252
}
1210
1253
@@ -1622,7 +1665,9 @@ impl<'a> ValidatingParser<'a> {
1622
1665
ParserState :: FunctionBodyLocals { ref locals } => {
1623
1666
let index = ( self . current_func_index + self . func_imports_count ) as usize ;
1624
1667
let ref func_type = self . types [ self . func_type_indices [ index] as usize ] ;
1625
- self . current_operator_validator = Some ( OperatorValidator :: new ( func_type, locals) ) ;
1668
+ let operator_config = self . config . operator_config ;
1669
+ self . current_operator_validator =
1670
+ Some ( OperatorValidator :: new ( func_type, locals, operator_config) ) ;
1626
1671
}
1627
1672
ParserState :: CodeOperator ( ref operator) => {
1628
1673
let check = self . current_operator_validator
@@ -1675,7 +1720,8 @@ impl<'a> ValidatingParser<'a> {
1675
1720
ParserState :: FunctionBodyLocals { ref locals } => {
1676
1721
let index = ( self . current_func_index + self . func_imports_count ) as usize ;
1677
1722
let ref func_type = self . types [ self . func_type_indices [ index] as usize ] ;
1678
- OperatorValidator :: new ( func_type, locals)
1723
+ let operator_config = self . config . operator_config ;
1724
+ OperatorValidator :: new ( func_type, locals, operator_config)
1679
1725
}
1680
1726
_ => panic ! ( "Invalid reader state" ) ,
1681
1727
} ;
@@ -1763,7 +1809,7 @@ impl<'b> ValidatingOperatorParser<'b> {
1763
1809
/// # 0x2, 0x83, 0x80, 0x80, 0x80, 0x0, 0x0, 0x1, 0xb, 0x83,
1764
1810
/// # 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0xb];
1765
1811
/// use wasmparser::{WasmDecoder, ParserState, ValidatingParser};
1766
- /// let mut parser = ValidatingParser::new(data);
1812
+ /// let mut parser = ValidatingParser::new(data, None );
1767
1813
/// let mut validating_parsers = Vec::new();
1768
1814
/// loop {
1769
1815
/// {
@@ -1813,8 +1859,8 @@ impl<'b> ValidatingOperatorParser<'b> {
1813
1859
1814
1860
/// Test whether the given buffer contains a valid WebAssembly module,
1815
1861
/// analogous to WebAssembly.validate in the JS API.
1816
- pub fn validate ( bytes : & [ u8 ] ) -> bool {
1817
- let mut parser = ValidatingParser :: new ( bytes) ;
1862
+ pub fn validate ( bytes : & [ u8 ] , config : Option < ValidatingParserConfig > ) -> bool {
1863
+ let mut parser = ValidatingParser :: new ( bytes, config ) ;
1818
1864
loop {
1819
1865
let state = parser. read ( ) ;
1820
1866
match * state {
@@ -1827,6 +1873,6 @@ pub fn validate(bytes: &[u8]) -> bool {
1827
1873
1828
1874
#[ test]
1829
1875
fn test_validate ( ) {
1830
- assert ! ( validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x1 , 0x0 , 0x0 , 0x0 ] ) ) ;
1831
- assert ! ( !validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x2 , 0x0 , 0x0 , 0x0 ] ) ) ;
1876
+ assert ! ( validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x1 , 0x0 , 0x0 , 0x0 ] , None ) ) ;
1877
+ assert ! ( !validate( & [ 0x0 , 0x61 , 0x73 , 0x6d , 0x2 , 0x0 , 0x0 , 0x0 ] , None ) ) ;
1832
1878
}
0 commit comments