@@ -63,6 +63,10 @@ impl Default for Gatekeeper {
6363 Self :: new ( GatekeeperConfig {
6464 allow_floats : true ,
6565 allow_feature_bulk_memory_operations : false ,
66+ // we allow the reference types proposal during compatibility checking because a subset
67+ // of it is required since Rust 1.82, but we don't allow any of the instructions specific
68+ // to the proposal here. Especially `table.grow` and `table.fill` can be abused to cause
69+ // very long runtime and high memory usage.
6670 allow_feature_reference_types : false ,
6771 allow_feature_simd : false ,
6872 allow_feature_exception_handling : false ,
@@ -444,4 +448,52 @@ mod tests {
444448 . to_string( )
445449 . contains( "Bulk memory operation" ) ) ;
446450 }
451+
452+ #[ test]
453+ fn bulk_table_operations_not_supported ( ) {
454+ // these operations can take a long time with big tables
455+ let deterministic = Arc :: new ( Gatekeeper :: default ( ) ) ;
456+ let mut compiler = make_compiler_config ( ) ;
457+ compiler. push_middleware ( deterministic) ;
458+ let store = Store :: new ( compiler) ;
459+
460+ let wasm = wat:: parse_str (
461+ r#"
462+ (module
463+ (table 2 funcref)
464+ (func (export "test") (param $i i32) (result i32)
465+ ;; grow table to size of $i
466+ ref.null func
467+ local.get $i
468+ table.grow 0))
469+ "# ,
470+ )
471+ . unwrap ( ) ;
472+
473+ let result = Module :: new ( & store, wasm) ;
474+ assert ! ( result
475+ . unwrap_err( )
476+ . to_string( )
477+ . contains( "Reference type operation" ) ) ;
478+
479+ let wasm = wat:: parse_str (
480+ r#"
481+ (module
482+ (table 1000000 funcref)
483+ (func (export "test") (param $i i32)
484+ ;; fill with nulls
485+ i32.const 0
486+ ref.null func
487+ i32.const 1000000
488+ table.fill 0))
489+ "# ,
490+ )
491+ . unwrap ( ) ;
492+
493+ let result = Module :: new ( & store, wasm) ;
494+ assert ! ( result
495+ . unwrap_err( )
496+ . to_string( )
497+ . contains( "Reference type operation" ) ) ;
498+ }
447499}
0 commit comments