Stream: git-wasmtime

Topic: wasmtime / issue #12813 pulley: ExtendedOpcode::MAX off-b...


view this post on Zulip Wasmtime GitHub notifications bot (Mar 20 2026 at 22:25):

gaynor-anthropic opened issue #12813:

ExtendedOpcode::MAX is computed as the variant count (N), not the max discriminant (N-1). new() checks bytes <= MAX, so new(N) passes validation and reaches transmute(N) on an invalid discriminant . Reachable via Disassembler::disassemble_all on 3 crafted bytes; Miri confirms. Niche optimisation currently masks it (Some(transmute(N)) bit-aliases None), but that's a layout coincidence.

Minimal PoC:

$ cat src/main.rs
//! `ExtendedOpcode::MAX` is the variant *count* (310), not the max
//! discriminant (309). `new()` checks `<= MAX`, so `new(310)` reaches
//! `transmute(310)` — UB. Miri catches it; natively it niche-collapses
//! to `None` by coincidence.
//!
//!     cargo +nightly miri run
#![forbid(unsafe_code)]

use pulley_interpreter::disas::Disassembler;
use pulley_interpreter::opcode::{ExtendedOpcode, Opcode};

fn main() {
    // Safe public disassembler → SafeBytecodeStream → ExtendedOpcode::new(MAX)
    let bytes = [
        Opcode::ExtendedOp as u8,
        ExtendedOpcode::MAX as u8,
        (ExtendedOpcode::MAX >> 8) as u8,
    ];
    let _ = Disassembler::disassemble_all(&bytes);
}
$ cargo miri run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `/root/.rustup/toolchains/nightly-2025-12-06-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/poc_bug_029`
error: Undefined Behavior: constructing invalid value at .<enum-tag>: encountered 0x0136, but expected a valid enum tag
   --> /root/home/opensrc/wasmtime/pulley/src/opcode.rs:104:18
    |
104 |         unsafe { core::mem::transmute(byte) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `pulley_interpreter::ExtendedOpcode::unchecked_new` at /root/home/opensrc/wasmtime/pulley/src/opcode.rs:104:18: 104:44
    = note: inside `pulley_interpreter::ExtendedOpcode::new` at /root/home/opensrc/wasmtime/pulley/src/opcode.rs:91:27: 91:53
    = note: inside `pulley_interpreter::decode::decode_one_extended::<pulley_interpreter::disas::Disassembler<'_>>` at /root/home/opensrc/wasmtime/pulley/src/decode.rs:707:26: 707:51
    = note: inside `pulley_interpreter::decode::Decoder::decode_one::<pulley_interpreter::disas::Disassembler<'_>>` at /root/home/opensrc/wasmtime/pulley/src/decode.rs:601:25: 601:53
    = note: inside `pulley_interpreter::decode::Decoder::decode_all::<'_, pulley_interpreter::disas::Disassembler<'_>>` at /root/home/opensrc/wasmtime/pulley/src/decode.rs:528:26: 528:53
    = note: inside `pulley_interpreter::disas::Disassembler::<'_>::disassemble_all` at /root/home/opensrc/wasmtime/pulley/src/disas.rs:32:9: 32:40
note: inside `main`
   --> src/main.rs:19:13
    |
 19 |     let _ = Disassembler::disassemble_all(&bytes);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

Not a security issue because pully is a tier 2 feature.


Last updated: Mar 23 2026 at 16:19 UTC