All advisories
Closed GHSA

Empty Component Panics Native DWARF Compilation

bytecodealliance/wasmtime / GHSA-27fw-gmrq-96pq

Affected packages

wasmtime rust
Affected versions<= 49.0.0
Patched versionsNot specified

Description

Empty Component Panics Native DWARF Compilation

Affected HEAD: 3ebfbe5af4927c157d6fcaca42b8dbb6d17b73fb
Sink: crates/cranelift/src/debug/transform/simulate.rs:300 in generate_simulated_dwarf
Observed verdict: valid component input panics the compiler

Summary

When native debug information is enabled, an attacker-supplied empty WebAssembly component reaches simulated-DWARF generation with no translated core modules. The compiler unwraps the first translation without checking that one exists, so the valid (component) input panics an unisolated compilation process instead of producing a component artifact or recoverable error.

Detail

build_component_artifacts accepts the empty component and later asks Cranelift to append DWARF. generate_simulated_dwarf in crates/cranelift/src/debug/transform/simulate.rs obtains its source file from:

let di = &compilation.translations.iter().next().unwrap().1.debuginfo;

An empty component has no core-module translations, so iter().next() returns None. The stock wasmtime compile -D debug-info=y path does not catch this panic. No custom embedding or harness is required; the reproducer passes the component directly to Wasmtime's existing compiler CLI.

Reproduce

set -eu
git clone --depth 1 https://github.com/bytecodealliance/wasmtime.git
cd wasmtime
git rev-parse HEAD

cargo build --bin wasmtime --no-default-features \
  --features 'run,wat,cranelift,compile,component-model,clap/default,clap/wrap_help'

printf '%s\n' '(component)' > empty-component.wat
set +e
RUST_BACKTRACE=0 ./target/debug/wasmtime compile -D debug-info=y \
  -o empty-component.cwasm empty-component.wat
status=$?
set -e
printf 'exit=%s\n' "$status"

Observed output on the affected HEAD:

3ebfbe5af4927c157d6fcaca42b8dbb6d17b73fb

thread 'main' (...) panicked at crates/cranelift/src/debug/transform/simulate.rs:300:58:
called `Option::unwrap()` on a `None` value
exit=101

Credit

Zheng Yu @ DepthFirst