A 15-byte malformed module panics the decoder on 32-bit targets. Verified on a clean checkout of main @ 096c71cfa.
Reader::read_vec_in (src/reader.rs:459) passes a module-supplied vector length straight to the allocator:
let len = self.read_u32()?;
let mut out = Vec::new_in(alloc, len)?;
Vec::new_in (src/util/vec.rs:137) then unwraps the layout:
unsafe { alloc.alloc(Layout::array::<T>(capacity as usize).unwrap())? }
On 32-bit isize::MAX is 2147483647, so a declared length of 0xFFFFFFFF overflows the layout for any element type and the unwrap panics. It runs before alloc.alloc, so a size-limited allocator does not protect against it.
The stack-based sibling already guards this: read_vec_stack (src/reader.rs:436-438) checks len and returns ValidationError::VecTooLong, which already exists and is already wired through the C API and the spec-test harness. Only the heap path skips it. read_vec feeds the type, import, function and global sections, code locals, FuncType signatures and export names, and is reachable from spacewasm_load_module.
Reproduce
The 32-bit regression suite is green first — 13 passed; 0 failed. Append to tests/regression/decode-errors.wast, a type section of size 5 declaring 0xFFFFFFFF entries:
(assert_invalid
(module binary "\00asm\01\00\00\00\01\05\ff\ff\ff\ff\0f")
"length out of bounds")
$ cargo test -p spacewasm --target i686-unknown-linux-gnu --test regression_integration decode_errors
test decode_errors ... FAILED
thread 'decode_errors' panicked at src/util/vec.rs:137:72:
called `Result::unwrap()` on an `Err` value: LayoutError
The same case passes on x86-64, where the layout is valid and the module is rejected with Eof — so it doubles as a regression test. Looks like an instance of #39.
#156 fixed this same unwrap shape in src/util/rc.rs but not in vec.rs; where the bound belongs is your call. Happy to send the test as a PR.
Disclosure per AI_POLICY.md. Tool: Claude Code. Assistance: bug diagnosis and reporting plus the .wast case; no AI-generated change to src/ is proposed. Every line reference and result comes from a clean checkout of 096c71cfa that I built and ran myself.
A 15-byte malformed module panics the decoder on 32-bit targets. Verified on a clean checkout of
main@096c71cfa.Reader::read_vec_in(src/reader.rs:459) passes a module-supplied vector length straight to the allocator:Vec::new_in(src/util/vec.rs:137) then unwraps the layout:On 32-bit
isize::MAXis2147483647, so a declared length of0xFFFFFFFFoverflows the layout for any element type and the unwrap panics. It runs beforealloc.alloc, so a size-limited allocator does not protect against it.The stack-based sibling already guards this:
read_vec_stack(src/reader.rs:436-438) checkslenand returnsValidationError::VecTooLong, which already exists and is already wired through the C API and the spec-test harness. Only the heap path skips it.read_vecfeeds the type, import, function and global sections, code locals,FuncTypesignatures and export names, and is reachable fromspacewasm_load_module.Reproduce
The 32-bit regression suite is green first —
13 passed; 0 failed. Append totests/regression/decode-errors.wast, a type section of size 5 declaring0xFFFFFFFFentries:The same case passes on x86-64, where the layout is valid and the module is rejected with
Eof— so it doubles as a regression test. Looks like an instance of #39.#156 fixed this same
unwrapshape insrc/util/rc.rsbut not invec.rs; where the bound belongs is your call. Happy to send the test as a PR.Disclosure per
AI_POLICY.md. Tool: Claude Code. Assistance: bug diagnosis and reporting plus the.wastcase; no AI-generated change tosrc/is proposed. Every line reference and result comes from a clean checkout of096c71cfathat I built and ran myself.