Skip to content

Instruction Metering Resume Corruption: Execution State Not Properly Restored Leading to "unreachable" Exceptions #4410

Open
@AlixANNERAUD

Description

@AlixANNERAUD

Test case

Any WebAssembly module with control flow instructions (loops, branches) will reproduce this issue. A minimal test case would be:

(module
  (func $test (export "test")
    (loop $loop
      br_if $loop (i32.const 1)
    )
  )
)

The issue occurs when setting an instruction limit and attempting to resume execution after hitting the limit.

Your environment

  • Host OS: Debian 12 Bookworm
  • WAMR version: 2.3.1
  • Platform: Desktop
  • CPU architecture: AMD64
  • Running mode: Interpreter mode with fast interpreter or classic interpreter
  • Build configuration: WASM_ENABLE_INSTRUCTION_METERING=1

Steps to reproduce

  1. Enable instruction metering: WASM_ENABLE_INSTRUCTION_METERING=1
  2. Create a WASM module with control flow instructions (loops, branches like the test case above)
  3. Set an instruction limit (e.g., 100-1000 instructions) using wasm_runtime_set_instruction_count_limit(...)
  4. Execute a function until it hits the instruction limit
  5. Resume execution by calling function
  6. Continue execution

Expected behavior

When instruction metering hits the configured limit:

  1. Execution should pause cleanly with the "instruction limit exceeded" exception
  2. The execution state (instruction pointer, stack, locals) should be preserved
  3. When resuming with a new instruction count, execution should continue from exactly where it left off
  4. The same instructions should not be re-executed from the beginning

Actual behavior

  1. First execution works correctly until instruction limit is reached
  2. When resuming, execution appears to restart from the beginning
  3. The same instructions are executed again (no resume from last instruction)
  4. Eventually crashes with "unreachable" exception (Exception: unreachable) when encountering a WASM_OP_BR_IF
  5. This suggests the execution state/stack is corrupted during the pause/resume cycle

Extra Info

The issue appears to be in the instruction metering implementation in wasm_interp_fast.c and wasm_interp_classic.c. There is no frame restoration logic may not properly preserve all necessary execution state when instruction metering interrupts execution.

I would be happy to work on solving this issue However, I would need some guidance from the maintainers on:

  1. Which execution state components need to be preserved?
  2. Memory allocation considerations:
    • Do we need to handle any allocations that might be partially completed when instruction limit is hit?
    • Are there any cleanup operations needed before suspension?
  3. Synchronization points:
    • What constitutes a "safe" point for instruction metering interruption?
    • Should we only check instruction limits at specific instruction boundaries?

Any guidance on these aspects would help me to fix this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions