Skip to content

Commit 1c97044

Browse files
michael-weigeltMichael Weigelt
andauthored
Make module validation deterministic in case of multiple errors (bytecodealliance#9947)
* make validation deterministic in case of multiple errors * test flag * smaller test --------- Co-authored-by: Michael Weigelt <[email protected]>
1 parent 40eea8e commit 1c97044

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

crates/wasmtime/src/engine.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,14 @@ impl Engine {
158158
#[cfg(feature = "parallel-compilation")]
159159
{
160160
use rayon::prelude::*;
161+
// If we collect into Result<Vec<B>, E> directly, the returned error is not
162+
// deterministic, because any error could be returned early. So we first materialize
163+
// all results in order and then return the first error deterministically, or Ok(_).
161164
return input
162165
.into_par_iter()
163166
.map(|a| f(a))
167+
.collect::<Vec<Result<B, E>>>()
168+
.into_iter()
164169
.collect::<Result<Vec<B>, E>>();
165170
}
166171
}

tests/all/module.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,27 @@ fn concurrent_type_modifications_and_checks(config: &mut Config) -> Result<()> {
534534

535535
Ok(())
536536
}
537+
538+
#[test]
539+
#[cfg_attr(miri, ignore)]
540+
fn validate_deterministic() {
541+
let mut faulty_wat = "(module ".to_string();
542+
for i in 0..100 {
543+
faulty_wat.push_str(&format!(
544+
"(func (export \"foo_{i}\") (result i64) (i64.add (i32.const 0) (i64.const 1)))"
545+
));
546+
}
547+
faulty_wat.push_str(")");
548+
let binary = wat::parse_str(faulty_wat).unwrap();
549+
550+
let engine_parallel = Engine::new(&Config::new().parallel_compilation(true)).unwrap();
551+
let result_parallel = Module::validate(&engine_parallel, &binary)
552+
.unwrap_err()
553+
.to_string();
554+
555+
let engine_sequential = Engine::new(&Config::new().parallel_compilation(false)).unwrap();
556+
let result_sequential = Module::validate(&engine_sequential, &binary)
557+
.unwrap_err()
558+
.to_string();
559+
assert_eq!(result_parallel, result_sequential);
560+
}

0 commit comments

Comments
 (0)