@@ -54,6 +54,9 @@ pub(crate) struct OperatorValidator {
5454 /// Offset of the `end` instruction which emptied the `control` stack, which
5555 /// must be the end of the function.
5656 end_which_emptied_control : Option < usize > ,
57+
58+ /// Whether validation is happening in a shared context.
59+ shared : bool ,
5760}
5861
5962// No science was performed in the creation of this number, feel free to change
@@ -274,6 +277,7 @@ impl OperatorValidator {
274277 operands,
275278 control,
276279 end_which_emptied_control : None ,
280+ shared : false ,
277281 }
278282 }
279283
@@ -300,17 +304,30 @@ impl OperatorValidator {
300304 unreachable : false ,
301305 init_height : 0 ,
302306 } ) ;
303- let params = OperatorValidatorTemp {
304- // This offset is used by the `func_type_at` and `inputs`.
307+
308+ // Retrieve the function's type via index (`ty`); the `offset` is
309+ // necessary due to `sub_type_at`'s error messaging.
310+ let sub_ty = OperatorValidatorTemp {
305311 offset,
306312 inner : & mut ret,
307313 resources,
308314 }
309- . func_type_at ( ty) ?
310- . params ( ) ;
311- for ty in params {
312- ret. locals . define ( 1 , * ty) ;
313- ret. local_inits . push ( true ) ;
315+ . sub_type_at ( ty) ?;
316+
317+ // Set up the function's locals.
318+ if let CompositeInnerType :: Func ( func_ty) = & sub_ty. composite_type . inner {
319+ for ty in func_ty. params ( ) {
320+ ret. locals . define ( 1 , * ty) ;
321+ ret. local_inits . push ( true ) ;
322+ }
323+ } else {
324+ bail ! ( offset, "expected func type at index {ty}, found {sub_ty}" )
325+ }
326+
327+ // If we're in a shared function, ensure we do not access unshared
328+ // objects.
329+ if sub_ty. composite_type . shared {
330+ ret. shared = true ;
314331 }
315332 Ok ( ret)
316333 }
@@ -912,14 +929,13 @@ where
912929 /// Returns the corresponding function type for the `func` item located at
913930 /// `function_index`.
914931 fn type_of_function ( & self , function_index : u32 ) -> Result < & ' resources FuncType > {
915- match self . resources . type_of_function ( function_index) {
916- Some ( f) => Ok ( f) ,
917- None => {
918- bail ! (
919- self . offset,
920- "unknown function {function_index}: function index out of bounds" ,
921- )
922- }
932+ if let Some ( type_index) = self . resources . type_index_of_function ( function_index) {
933+ self . func_type_at ( type_index)
934+ } else {
935+ bail ! (
936+ self . offset,
937+ "unknown function {function_index}: function index out of bounds" ,
938+ )
923939 }
924940 }
925941
@@ -971,7 +987,7 @@ where
971987 /// table.
972988 ///
973989 /// The return value of this function is the function type behind
974- /// `type_index` which must then be passedt o `check_{call,return_call}_ty`.
990+ /// `type_index` which must then be passed to `check_{call,return_call}_ty`.
975991 fn check_call_indirect_ty (
976992 & mut self ,
977993 type_index : u32 ,
@@ -1302,6 +1318,12 @@ where
13021318 fn struct_type_at ( & self , at : u32 ) -> Result < & ' resources StructType > {
13031319 let sub_ty = self . sub_type_at ( at) ?;
13041320 if let CompositeInnerType :: Struct ( struct_ty) = & sub_ty. composite_type . inner {
1321+ if self . inner . shared && !sub_ty. composite_type . shared {
1322+ bail ! (
1323+ self . offset,
1324+ "shared functions cannot access unshared structs" ,
1325+ ) ;
1326+ }
13051327 Ok ( struct_ty)
13061328 } else {
13071329 bail ! (
@@ -1342,6 +1364,12 @@ where
13421364 fn array_type_at ( & self , at : u32 ) -> Result < FieldType > {
13431365 let sub_ty = self . sub_type_at ( at) ?;
13441366 if let CompositeInnerType :: Array ( array_ty) = & sub_ty. composite_type . inner {
1367+ if self . inner . shared && !sub_ty. composite_type . shared {
1368+ bail ! (
1369+ self . offset,
1370+ "shared functions cannot access unshared arrays" ,
1371+ ) ;
1372+ }
13451373 Ok ( array_ty. 0 )
13461374 } else {
13471375 bail ! (
@@ -1365,6 +1393,12 @@ where
13651393 fn func_type_at ( & self , at : u32 ) -> Result < & ' resources FuncType > {
13661394 let sub_ty = self . sub_type_at ( at) ?;
13671395 if let CompositeInnerType :: Func ( func_ty) = & sub_ty. composite_type . inner {
1396+ if self . inner . shared && !sub_ty. composite_type . shared {
1397+ bail ! (
1398+ self . offset,
1399+ "shared functions cannot access unshared functions" ,
1400+ ) ;
1401+ }
13681402 Ok ( func_ty)
13691403 } else {
13701404 bail ! (
@@ -1382,6 +1416,12 @@ where
13821416
13831417 fn global_type_at ( & self , at : u32 ) -> Result < GlobalType > {
13841418 if let Some ( ty) = self . resources . global_at ( at) {
1419+ if self . inner . shared && !ty. shared {
1420+ bail ! (
1421+ self . offset,
1422+ "shared functions cannot access unshared globals" ,
1423+ ) ;
1424+ }
13851425 Ok ( ty)
13861426 } else {
13871427 bail ! ( self . offset, "unknown global: global index out of bounds" ) ;
@@ -1391,7 +1431,15 @@ where
13911431 /// Validates that the `table` is valid and returns the type it points to.
13921432 fn table_type_at ( & self , table : u32 ) -> Result < TableType > {
13931433 match self . resources . table_at ( table) {
1394- Some ( ty) => Ok ( ty) ,
1434+ Some ( ty) => {
1435+ if self . inner . shared && !ty. shared {
1436+ bail ! (
1437+ self . offset,
1438+ "shared functions cannot access unshared tables" ,
1439+ ) ;
1440+ }
1441+ Ok ( ty)
1442+ }
13951443 None => bail ! (
13961444 self . offset,
13971445 "unknown table {table}: table index out of bounds"
0 commit comments