Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: upgrade wasmtime to 26 #2205

Merged
merged 12 commits into from
Nov 5, 2024
749 changes: 414 additions & 335 deletions Cargo.Bazel.Fuzzing.json.lock

Large diffs are not rendered by default.

194 changes: 105 additions & 89 deletions Cargo.Bazel.Fuzzing.toml.lock

Large diffs are not rendered by default.

749 changes: 414 additions & 335 deletions Cargo.Bazel.json.lock

Large diffs are not rendered by default.

194 changes: 105 additions & 89 deletions Cargo.Bazel.toml.lock

Large diffs are not rendered by default.

208 changes: 109 additions & 99 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bazel/external_crates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,7 @@ def external_crates_repository(name, cargo_lockfile, lockfile, sanitizers_enable
version = "^0.217.0",
),
"wasmtime": crate.spec(
version = "=25.0.2",
version = "^26.0.0",
default_features = False,
features = [
"cranelift",
Expand All @@ -1435,7 +1435,7 @@ def external_crates_repository(name, cargo_lockfile, lockfile, sanitizers_enable
],
),
"wasmtime-environ": crate.spec(
version = "^25.0.0",
version = "^26.0.0",
),
"wast": crate.spec(
version = "^212.0.0",
Expand Down
4 changes: 2 additions & 2 deletions rs/embedders/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ slog = { workspace = true }
slog-term = { workspace = true }
wasm-encoder = { workspace = true }
wasmparser = { workspace = true }
wasmtime = { version = "25.0.0", default-features = false, features = [
wasmtime = { version = "26.0.0", default-features = false, features = [
'cranelift',
'gc',
'parallel-compilation',
'runtime',
] }
wasmtime-environ = "25.0.0"
wasmtime-environ = "26.0.0"

# Wasmtime depends on 0.4.2 but specifies 0.4.1 in the toml file.
# Enforce 0.4.2 using a dummy dependency until the upstream issue
Expand Down
4 changes: 2 additions & 2 deletions rs/embedders/src/wasmtime_embedder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub(crate) const STABLE_MEMORY_NAME: &str = "stable_memory";
pub(crate) const STABLE_BYTEMAP_MEMORY_NAME: &str = "stable_bytemap_memory";

pub(crate) const MAX_STORE_TABLES: usize = 1;
pub(crate) const MAX_STORE_TABLE_ELEMENTS: u32 = 1_000_000;
pub(crate) const MAX_STORE_TABLE_ELEMENTS: usize = 1_000_000;

fn demangle(func_name: &str) -> String {
if let Ok(name) = rustc_demangle::try_demangle(func_name) {
Expand Down Expand Up @@ -1043,7 +1043,7 @@ impl WasmtimeInstance {
.ok_or_else(|| HypervisorError::ToolchainContractViolation {
error: "export 'table' is not a table".to_string(),
})?
.get(&mut self.store, closure.func_idx)
.get(&mut self.store, closure.func_idx as u64)
.ok_or(HypervisorError::FunctionNotFound(0, closure.func_idx))?
.as_func()
.ok_or_else(|| HypervisorError::ToolchainContractViolation {
Expand Down
97 changes: 74 additions & 23 deletions rs/embedders/tests/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,41 +1080,92 @@ fn charge_for_dirty_stable() {
run_charge_for_dirty_stable_test(FlagStatus::Disabled);
}

#[test]
fn table_modifications_are_unsupported() {
fn test(code: &str) -> String {
let wat = format!(
r#"(module
(table $table 101 funcref)
(elem func 0)
(func $f {code})
)"#
);
let embedder = WasmtimeEmbedder::new(EmbeddersConfig::default(), no_op_logger());
let wasm = wat::parse_str(wat).expect("Failed to convert wat to wasm");

wasm_utils::compile(&embedder, &BinaryEncodedWasm::new(wasm))
.1
.unwrap_err()
.to_string()
}
/// Helper method to generate a wasm module with tables in both
/// 32 and 64 bit modes and compile that module. The method
/// is then used to check if instrumentation of tables works
/// correctly for both Wasm32 and Wasm64 wrt tables.
fn test_table_validation(code: &str, is_wasm64: bool) -> String {
let execution_mode = if is_wasm64 { "i64" } else { "" };
let wat = format!(
r#"(module
(table $table {execution_mode} 101 funcref)
(elem func 0)
(func $f {code})

)"#
);
use ic_config::embedders::FeatureFlags;
use ic_config::flag_status::FlagStatus;

let embedders_config = EmbeddersConfig {
feature_flags: FeatureFlags {
wasm64: if is_wasm64 {
FlagStatus::Enabled
} else {
FlagStatus::Disabled
},
..Default::default()
},
..Default::default()
};

let embedder = WasmtimeEmbedder::new(embedders_config, no_op_logger());
let wasm = wat::parse_str(wat).expect("Failed to convert wat to wasm");

wasm_utils::compile(&embedder, &BinaryEncodedWasm::new(wasm))
.1
.unwrap_err()
.to_string()
}

fn table_modifications_are_unsupported_for_wasm_version(is_wasm64: bool) {
let address_type = if is_wasm64 { "i64" } else { "i32" };

let err = test("(drop (table.grow $table (ref.func 0) (i32.const 0)))");
let err = test_table_validation(
&format!("(drop (table.grow $table (ref.func 0) ({address_type}.const 0)))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.grow"));

let err = test("(table.set $table (i32.const 0) (ref.func 0))");
let err = test_table_validation(
&format!("(table.set $table ({address_type}.const 0) (ref.func 0))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.set"));

let err = test("(table.fill $table (i32.const 0) (ref.func 0) (i32.const 50))");
let err = test_table_validation(
&format!(
"(table.fill $table ({address_type}.const 0) (ref.func 0) ({address_type}.const 50))"
),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.fill"));

let err = test("(table.copy (i32.const 0) (i32.const 0) (i32.const 0))");
let err = test_table_validation(
&format!(
"(table.copy ({address_type}.const 0) ({address_type}.const 0) ({address_type}.const 0))"
),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.copy"));

let err = test("(table.init 0 (i32.const 0) (i32.const 0) (i32.const 0))");
let err = test_table_validation(
&format!("(table.init 0 ({address_type}.const 0) (i32.const 0) (i32.const 0))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.init"));
}

#[test]
fn table_modifications_are_unsupported_for_wasm32() {
table_modifications_are_unsupported_for_wasm_version(false);
}

#[test]
fn table_modifications_are_unsupported_for_wasm64() {
table_modifications_are_unsupported_for_wasm_version(true);
}

#[test]
fn metering_wasm64_load_store_canister() {
let wat = r#"
Expand Down
27 changes: 27 additions & 0 deletions rs/embedders/tests/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,3 +1196,30 @@ fn test_wasm64_initial_wasm_memory_size_validation() {
})
);
}

#[test]
fn test_validate_table64() {
use ic_config::embedders::FeatureFlags;
use ic_config::flag_status::FlagStatus;

let embedders_config = EmbeddersConfig {
feature_flags: FeatureFlags {
wasm64: FlagStatus::Enabled,
..Default::default()
},
..Default::default()
};

let wasm = wat2wasm(
r#"(module
(table i64 1 funcref)
(memory i64 1 1)
)"#,
)
.unwrap();

assert_eq!(
validate_wasm_binary(&wasm, &embedders_config),
Ok(WasmValidationDetails::default())
);
}