From df0f32f44b1fccd41b2eafac4b637a7ac9288e4b Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 26 Mar 2025 13:00:52 +0100 Subject: [PATCH 1/3] Enable reference-types in static-analysis, but not Gatekeeper --- packages/vm/src/parsed_wasm.rs | 3 ++- packages/vm/src/wasm_backend/gatekeeper.rs | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/vm/src/parsed_wasm.rs b/packages/vm/src/parsed_wasm.rs index c5d8c416f..bfbbff3bc 100644 --- a/packages/vm/src/parsed_wasm.rs +++ b/packages/vm/src/parsed_wasm.rs @@ -77,7 +77,8 @@ impl<'a> ParsedWasm<'a> { | WasmFeatures::SATURATING_FLOAT_TO_INT | WasmFeatures::SIGN_EXTENSION | WasmFeatures::MULTI_VALUE - | WasmFeatures::FLOATS; + | WasmFeatures::FLOATS + | WasmFeatures::REFERENCE_TYPES; let mut validator = Validator::new_with_features(features); diff --git a/packages/vm/src/wasm_backend/gatekeeper.rs b/packages/vm/src/wasm_backend/gatekeeper.rs index 573b53a9a..cdcc4e474 100644 --- a/packages/vm/src/wasm_backend/gatekeeper.rs +++ b/packages/vm/src/wasm_backend/gatekeeper.rs @@ -62,8 +62,12 @@ impl Default for Gatekeeper { fn default() -> Self { Self::new(GatekeeperConfig { allow_floats: true, - allow_feature_bulk_memory_operations: false, + // we allow the reference types proposal during compatibility checking because a subset + // of it is required since Rust 1.82, but we don't allow any of the instructions specific + // to the proposal here. Especially `table.grow` and `table.fill` can be abused to cause + // very long runtime and high memory usage. allow_feature_reference_types: false, + allow_feature_bulk_memory_operations: false, allow_feature_simd: false, allow_feature_exception_handling: false, allow_feature_threads: false, From 7fe95a1a85bf442134f22c0f68f6dbd28855c1f2 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 26 Mar 2025 13:45:16 +0100 Subject: [PATCH 2/3] Add tests --- packages/vm/src/wasm_backend/compile.rs | 13 ++++++ packages/vm/src/wasm_backend/gatekeeper.rs | 48 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/packages/vm/src/wasm_backend/compile.rs b/packages/vm/src/wasm_backend/compile.rs index 6c85bfe4e..778601e73 100644 --- a/packages/vm/src/wasm_backend/compile.rs +++ b/packages/vm/src/wasm_backend/compile.rs @@ -20,4 +20,17 @@ mod tests { let engine = make_compiling_engine(None); assert!(compile(&engine, FLOATY).is_ok()); } + + #[test] + fn reference_types_dont_panic() { + const WASM: &str = r#"(module + (type $t0 (func (param funcref externref))) + (import "" "" (func $hello (type $t0))) + )"#; + + let wasm = wat::parse_str(WASM).unwrap(); + let engine = make_compiling_engine(None); + let error = compile(&engine, &wasm).unwrap_err(); + assert!(error.to_string().contains("FuncRef")); + } } diff --git a/packages/vm/src/wasm_backend/gatekeeper.rs b/packages/vm/src/wasm_backend/gatekeeper.rs index cdcc4e474..d7ddd4c8d 100644 --- a/packages/vm/src/wasm_backend/gatekeeper.rs +++ b/packages/vm/src/wasm_backend/gatekeeper.rs @@ -465,4 +465,52 @@ mod tests { .to_string() .contains("Bulk memory operation")); } + + #[test] + fn bulk_table_operations_not_supported() { + // these operations can take a long time with big tables + let deterministic = Arc::new(Gatekeeper::default()); + let mut compiler = make_compiler_config(); + compiler.push_middleware(deterministic); + let store = Store::new(compiler); + + let wasm = wat::parse_str( + r#" + (module + (table 2 funcref) + (func (export "test") (param $i i32) (result i32) + ;; grow table to size of $i + ref.null func + local.get $i + table.grow 0)) + "#, + ) + .unwrap(); + + let result = Module::new(&store, wasm); + assert!(result + .unwrap_err() + .to_string() + .contains("Reference type operation")); + + let wasm = wat::parse_str( + r#" + (module + (table 1000000000 funcref) + (func (export "test") (param $i i32) + ;; fill with nulls + i32.const 0 + ref.null func + i32.const 1000000000 + table.fill 0)) + "#, + ) + .unwrap(); + + let result = Module::new(&store, wasm); + assert!(result + .unwrap_err() + .to_string() + .contains("Reference type operation")); + } } From fcacb3e3fd9943c822b164d9f3f3c75160edc8c8 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 26 Mar 2025 14:18:09 +0100 Subject: [PATCH 3/3] Compile hackatom with newer Rust version --- .circleci/config.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 336c8c38e..9f1c6641e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -731,7 +731,8 @@ jobs: contract_hackatom: docker: - - image: rust:1.81 + # We compile this contract with the upper bound to detect issues with new Rust versions early + - image: rust:1.84.1 environment: RUST_BACKTRACE: 1 working_directory: ~/cosmwasm/contracts/hackatom @@ -743,9 +744,9 @@ jobs: command: rustc --version; cargo --version; rustup --version - restore_cache: keys: - - cargocache-v2-contract_hackatom-rust:1.81-{{ checksum "Cargo.lock" }} + - cargocache-v2-contract_hackatom-rust:1.84.1-{{ checksum "Cargo.lock" }} - check_contract: - min_version: "2.2" + min_version: "3.0" - save_cache: paths: - /usr/local/cargo/registry @@ -755,7 +756,7 @@ jobs: - target/wasm32-unknown-unknown/release/.fingerprint - target/wasm32-unknown-unknown/release/build - target/wasm32-unknown-unknown/release/deps - key: cargocache-v2-contract_hackatom-rust:1.81-{{ checksum "Cargo.lock" }} + key: cargocache-v2-contract_hackatom-rust:1.84.1-{{ checksum "Cargo.lock" }} contract_ibc_callbacks: docker: