Skip to content

Commit 72d2bc2

Browse files
michael-weigeltMichael Weigeltlwshang
authored
Validate the manipulated module before emitting it and give a warning if that fails. (#80)
* features into array * validate module before emitting it * more explicit flags * fix * changelog * bump to 0.9.3 --------- Co-authored-by: Michael Weigelt <michael.weigelt@dfinity.com> Co-authored-by: Linwei Shang <linwei.shang@dfinity.org>
1 parent bdc074a commit 72d2bc2

File tree

6 files changed

+105
-21
lines changed

6 files changed

+105
-21
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [unreleased]
88

9+
## [0.9.3] - 2024-01-10
10+
11+
* Validate the manipulated module before emitting it and give a warning if that fails.
12+
913
## [0.9.2] - 2024-01-09
1014

1115
* Fix: limit_resource works with wasm64.

Cargo.lock

Lines changed: 32 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ic-wasm"
3-
version = "0.9.2"
3+
version = "0.9.3"
44
authors = ["DFINITY Stiftung"]
55
edition = "2021"
66
description = "A library for performing Wasm transformations specific to canisters running on the Internet Computer"
@@ -20,11 +20,12 @@ required-features = ["exe"]
2020
[dependencies]
2121
# Major version bump of walrus should result in a major version bump of ic-wasm.
2222
# Because we expose walrus types in ic-wasm public API.
23-
walrus = "0.22.0"
23+
walrus = "0.22.0"
2424
candid = "0.10"
2525
rustc-demangle = "0.1"
2626
thiserror = "1.0.35"
2727
libflate = "2.0"
28+
wasmparser = "0.223.0"
2829

2930
wasm-opt = { version = "0.116.0", optional = true }
3031
tempfile = { version = "3.5.0", optional = true }
@@ -44,4 +45,4 @@ assert_cmd = "2"
4445

4546
[package.metadata.binstall]
4647
pkg-url = "{ repo }/releases/download/{ version }/{ name }-{ target }{ archive-suffix }"
47-
pkg-fmt = "tgz" # archive-suffix = .tar.gz
48+
pkg-fmt = "tgz" # archive-suffix = .tar.gz

src/bin/main.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clap::{crate_authors, crate_version, Parser};
2+
use ic_wasm::utils::make_validator_with_features;
23
use std::path::PathBuf;
34

45
#[derive(Parser)]
@@ -202,8 +203,15 @@ fn main() -> anyhow::Result<()> {
202203
}
203204
}
204205
};
206+
// validate new module
207+
let module_bytes = m.emit_wasm();
208+
let mut validator = make_validator_with_features();
209+
if let Err(e) = validator.validate_all(&module_bytes) {
210+
println!("WARNING: The output of ic-wasm failed to validate. Please report this via github issue or on https://forum.dfinity.org/");
211+
eprintln!("{e}");
212+
}
205213
if let Some(output) = opts.output {
206-
m.emit_wasm_file(output)?;
214+
std::fs::write(output, module_bytes).expect("failed to write wasm module");
207215
}
208216
Ok(())
209217
}

src/optimize.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,10 @@ pub fn optimize(
9090
if let Some(max_size) = always_inline_max_function_size {
9191
optimizations.always_inline_max_size(*max_size);
9292
}
93-
// The feature set should be align with IC `wasmtime` validation config:
94-
// https://github.com/dfinity/ic/blob/6a6470d705a0f36fb94743b12892280409f85688/rs/embedders/src/wasm_utils/validation.rs#L1385
95-
optimizations.enable_feature(wasm_opt::Feature::MutableGlobals);
96-
optimizations.enable_feature(wasm_opt::Feature::TruncSat);
97-
optimizations.enable_feature(wasm_opt::Feature::Simd);
98-
optimizations.enable_feature(wasm_opt::Feature::BulkMemory);
99-
optimizations.enable_feature(wasm_opt::Feature::SignExt);
100-
optimizations.enable_feature(wasm_opt::Feature::ReferenceTypes);
101-
optimizations.enable_feature(wasm_opt::Feature::Memory64);
93+
94+
for feature in IC_ENABLED_WASM_FEATURES {
95+
optimizations.enable_feature(feature);
96+
}
10297
optimizations.run(temp_file.path(), temp_file.path())?;
10398

10499
// read optimized wasm back in from temp file

src/utils.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,63 @@ use std::borrow::Cow;
44
use std::collections::HashMap;
55
use std::io::{self, Read};
66
use walrus::*;
7+
use wasm_opt::Feature;
8+
use wasmparser::{Validator, WasmFeaturesInflated};
79

810
pub const WASM_MAGIC_BYTES: &[u8] = &[0, 97, 115, 109];
911

1012
pub const GZIPPED_WASM_MAGIC_BYTES: &[u8] = &[31, 139, 8];
1113

14+
// The feature set should be align with IC `wasmtime` validation config:
15+
// https://github.com/dfinity/ic/blob/6a6470d705a0f36fb94743b12892280409f85688/rs/embedders/src/wasm_utils/validation.rs#L1385
16+
// Since we use both wasm_opt::Feature and wasmparse::WasmFeature, we have to define the config/features for both.
17+
pub const IC_ENABLED_WASM_FEATURES: [Feature; 7] = [
18+
Feature::MutableGlobals,
19+
Feature::TruncSat,
20+
Feature::Simd,
21+
Feature::BulkMemory,
22+
Feature::SignExt,
23+
Feature::ReferenceTypes,
24+
Feature::Memory64,
25+
];
26+
27+
pub const IC_ENABLED_WASM_FEATURES_INFLATED: WasmFeaturesInflated = WasmFeaturesInflated {
28+
mutable_global: true,
29+
saturating_float_to_int: true,
30+
sign_extension: true,
31+
reference_types: true,
32+
multi_value: true,
33+
bulk_memory: true,
34+
simd: true,
35+
relaxed_simd: false,
36+
threads: true,
37+
shared_everything_threads: true,
38+
tail_call: false,
39+
floats: true,
40+
multi_memory: true,
41+
exceptions: true,
42+
memory64: true,
43+
extended_const: true,
44+
component_model: true,
45+
function_references: false,
46+
memory_control: true,
47+
gc: false,
48+
custom_page_sizes: true,
49+
component_model_values: true,
50+
component_model_nested_names: true,
51+
component_model_more_flags: true,
52+
component_model_multiple_returns: true,
53+
legacy_exceptions: true,
54+
gc_types: true,
55+
stack_switching: true,
56+
wide_arithmetic: false,
57+
component_model_async: true,
58+
};
59+
60+
pub fn make_validator_with_features() -> Validator {
61+
Validator::new_with_features(IC_ENABLED_WASM_FEATURES_INFLATED.into())
62+
}
63+
1264
fn wasm_parser_config(keep_name_section: bool) -> ModuleConfig {
1365
let mut config = walrus::ModuleConfig::new();
1466
config.generate_name_section(keep_name_section);

0 commit comments

Comments
 (0)