Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

The segmentation fault (SIGSEGV) in the wasm_interp_call_func_bytecode #2577

Closed
khagankhan opened this issue Sep 21, 2023 · 2 comments
Closed

Comments

@khagankhan
Copy link

khagankhan commented Sep 21, 2023

Describe the Bug

The segmentation fault (SIGSEGV) occurred in the wasm_interp_call_func_bytecode function at wasm_interp_fast.c:2639, specifically on the HANDLE_OP_END(); line.

iwasm --version: iwasm 1.2.3

uname -a: Linux node0.wamr.randtest-pg0.utah.cloudlab.us 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Steps to reproduce:

  1. Save the crash.wat (Remove .txt extension)
  2. Install and build WABT toolkit (wat2wasm from WABT can be used to convert crash.wat into crash.wasm using: wat2wasm crash.wat -o crash.wasm. I have also added crash.wasm that obviates the need to use wat2wasm)
  3. Run iwasm crash.wasm
  4. Observe the segfault

Files that cause the segfault:

crash.wat.txt (Remove .txt extension when you save it)

crash.wasm.txt (Remove .txt extension when you save it)

Reduced modules:

shrunk.wat.txt (Remove .txt extension when you save it)

shrunk.wasm.txt (Remove .txt extension when you save it)

Observed Behavior:

iwasm crash.wasm 
Segmentation fault

Expected behavior:

iwasm is supposed to run the module successfully. wasmer and wasmtime run the module successfully.

GDB Backtrace

Program received signal SIGSEGV, Segmentation fault.
wasm_interp_call_func_bytecode (module=0x55555588ac20, exec_env=0x14, exec_env@entry=0x55555588b210, cur_func=0x555555889b00, prev_frame=0x1, prev_frame@entry=0x55555588b2a8) at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_interp_fast.c:2639
2639	                HANDLE_OP_END();
(gdb) bt
#0  wasm_interp_call_func_bytecode (module=0x55555588ac20, exec_env=0x14, exec_env@entry=0x55555588b210, 
    cur_func=0x555555889b00, prev_frame=0x1, prev_frame@entry=0x55555588b2a8)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_interp_fast.c:2639
#1  0x00005555555e8014 in wasm_interp_call_wasm (module_inst=module_inst@entry=0x55555588ac20, 
    exec_env=exec_env@entry=0x55555588b210, function=function@entry=0x555555889ad0, argc=<optimized out>, 
    argc@entry=0, argv=argv@entry=0x7fffffffdf70)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_interp_fast.c:4019
#2  0x000055555558c355 in call_wasm_with_hw_bound_check (module_inst=module_inst@entry=0x55555588ac20, 
    exec_env=exec_env@entry=0x55555588b210, function=function@entry=0x555555889ad0, argc=argc@entry=0, 
    argv=argv@entry=0x7fffffffdf70) at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_runtime.c:2337
#3  0x000055555558eab1 in wasm_call_function (exec_env=exec_env@entry=0x55555588b210, 
    function=function@entry=0x555555889ad0, argc=argc@entry=0, argv=argv@entry=0x7fffffffdf70)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_runtime.c:2404
#4  0x00005555555841ac in wasm_runtime_call_wasm (exec_env=exec_env@entry=0x55555588b210, 
    function=function@entry=0x555555889ad0, argc=argc@entry=0, argv=argv@entry=0x7fffffffdf70)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/common/wasm_runtime_common.c:1989
#5  0x000055555557d1a8 in execute_main (argv=<optimized out>, argc=<optimized out>, 
    module_inst=0x555555687a20 <__afl_area_initial>)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/common/wasm_application.c:218
#6  wasm_application_execute_main (module_inst=module_inst@entry=0x55555588ac20, argc=<optimized out>, 
    argv=<optimized out>) at /root/wasmoi/wasm-micro-runtime/core/iwasm/common/wasm_application.c:238
#7  0x0000555555578c5d in app_instance_main (module_inst=0x55555588ac20)
    at /root/wasmoi/wasm-micro-runtime/product-mini/platforms/linux/../posix/main.c:122
#8  main (argc=<optimized out>, argv=<optimized out>)
    at /root/wasmoi/wasm-micro-runtime/product-mini/platforms/linux/../posix/main.c:981

The WASM module that caused the segfault (cat crash.wat):

(module (memory $mem 1) (table 1 funcref)
   (elem (i32.const 0) $lift_3)
   (func
    $main
    (export "_main")
    (result i32)
    (local $i32_storage i32)
    (local $i64_storage i64)
    (local $f32_storage f32)
    (local $f64_storage f64)
    i32.const
    533
    i32.load8_s
    offset=57
    align=1
    i32.const
    428
    i64.load32_u
    offset=70
    align=2
    i32.const
    0
    call_indirect
    (param i32)
    (param i64)
    (result f64)
    call
    $lift_1)
   (func
    $lift_3
    (param $param_4 i32)
    (param $param_5 i64)
    (result f64)
    (local $i32_storage i32)
    (local $i64_storage i64)
    (local $f32_storage f32)
    (local $f64_storage f64)
    (local $lift_8 f64)
    (local $lift_6 f64)
    (local $loop_7_storage f64)
    (local $loop_7_counter i32)
    local.get
    $lift_6
    i32.const
    21
    local.set
    $loop_7_counter
    local.get
    $lift_6
    f64.const
    -89.51973260359475
    i32.const
    293
    f64.load
    offset=88
    align=2
    local.tee
    $f64_storage
    local.get
    $f64_storage
    i64.reinterpret_f64
    i64.const
    0x7FF0000000000000
    i64.and
    i64.popcnt
    i64.const
    11
    i64.eq
    select
    local.tee
    $f64_storage
    f64.min
    local.set
    $loop_7_storage
    loop
    local.get
    $loop_7_storage
    f64.const
    -159.6315110918028
    i32.const
    677
    f64.load
    offset=84
    align=1
    local.tee
    $f64_storage
    local.get
    $f64_storage
    i64.reinterpret_f64
    i64.const
    0x7FF0000000000000
    i64.and
    i64.popcnt
    i64.const
    11
    i64.eq
    select
    local.tee
    $f64_storage
    f64.add
    local.set
    $loop_7_storage
    local.get
    $loop_7_counter
    i32.const
    -1
    i32.add
    local.tee
    $loop_7_counter
    br_if
    0
    end
    local.get
    $loop_7_storage
    f64.sub
    block
    (result f64)
    f64.const
    6.53664948805773
    i32.const
    666
    f64.load
    offset=8
    align=4
    local.tee
    $f64_storage
    local.get
    $f64_storage
    i64.reinterpret_f64
    i64.const
    0x7FF0000000000000
    i64.and
    i64.popcnt
    i64.const
    11
    i64.eq
    select
    local.tee
    $f64_storage
    br
    0
    f64.const
    862.3687155155216
    i32.const
    760
    f64.load
    offset=83
    align=1
    local.tee
    $f64_storage
    local.get
    $f64_storage
    i64.reinterpret_f64
    i64.const
    0x7FF0000000000000
    i64.and
    i64.popcnt
    i64.const
    11
    i64.eq
    select
    local.tee
    $f64_storage
    local.tee
    $lift_8
    f64.max
    end
    f64.sub)
   (func
    $lift_1
    (param $param_2 f64)
    (result i32)
    (local $i32_storage i32)
    (local $i64_storage i64)
    (local $f32_storage f32)
    (local $f64_storage f64)
    i32.const
    429
    i32.load
    offset=33
    align=2))

Reduced code that caused the segfault (cat shrunk.wat):

(module
  (type (;0;) (func (result i32)))
  (type (;1;) (func (param i32 i64) (result f64)))
  (type (;2;) (func (param f64) (result i32)))
  (func (;0;) (type 0) (result i32)
    (local i32 i64 f32 f64)
    i32.const 533
    i32.load8_s offset=57
    i32.const 428
    i64.load32_u offset=70 align=2
    i32.const 0
    call_indirect (type 1)
    call 2
  )
  (func (;1;) (type 1) (param i32 i64) (result f64)
    (local i32 i64 f32 f64 f64 f64 f64 i32)
    local.get 7
    i32.const 21
    local.set 9
    local.get 7
    f64.const -0x1.661434c89c6aep+6 (;=-89.51973260359475;)
    i32.const 293
    f64.load offset=88 align=2
    local.tee 5
    local.get 5
    i64.reinterpret_f64
    i64.const 9218868437227405312
    i64.and
    i64.popcnt
    i64.const 11
    i64.eq
    select
    local.tee 5
    f64.min
    local.set 8
    loop ;; label = @1
      local.get 8
      local.get 5
      f64.add
      local.set 8
      local.get 9
      i32.const -1
      i32.add
      local.tee 9
      br_if 0 (;@1;)
    end
    local.get 8
    f64.sub
    block (result f64) ;; label = @1
      f64.const 0x1.a258771827e0cp+2 (;=6.53664948805773;)
      i32.const 666
      f64.load offset=8 align=4
      local.tee 5
      local.get 5
      i64.reinterpret_f64
      i64.const 9218868437227405312
      i64.and
      i64.popcnt
      i64.const 11
      i64.eq
      select
      local.tee 5
      br 0 (;@1;)
      f64.const 0x1.af2f3211ec58bp+9 (;=862.3687155155216;)
      i32.const 760
      f64.load offset=83 align=1
      local.tee 5
      local.get 5
      i64.reinterpret_f64
      i64.const 9218868437227405312
      i64.and
      i64.popcnt
      i64.const 11
      i64.eq
      select
      local.tee 5
      local.tee 6
      f64.max
    end
    f64.sub
  )
  (func (;2;) (type 2) (param f64) (result i32)
    unreachable
  )
  (table (;0;) 1 funcref)
  (memory (;0;) 1)
  (export "_main" (func 0))
  (elem (;0;) (i32.const 0) func 1)
)

Additional information

A combination of AFL++ and Wasmlike, an Xsmith-based random program generator produced the snippet of code that found the issue. Xsmith Project

@wenyongh
Copy link
Contributor

Hi, thanks for reporting the issue! I fixed it with #2590, could you try again?

wenyongh added a commit that referenced this issue Sep 26, 2023
`wasm_loader_push_pop_frame_offset` may pop n operands by using
`loader_ctx->stack_cell_num` to check whether the operand can be
popped or not. While `loader_ctx->stack_cell_num` is updated in the
later `wasm_loader_push_pop_frame_ref`, the check may fail if the stack
is in polymorphic state and lead to `ctx->frame_offset` underflow.

Fix issue #2577 and #2586.
@khagankhan
Copy link
Author

Thank you very much! It appears to be fixed. Thanks for prompt response!

victoryang00 pushed a commit to victoryang00/wamr-aot-gc-checkpoint-restore that referenced this issue May 27, 2024
`wasm_loader_push_pop_frame_offset` may pop n operands by using
`loader_ctx->stack_cell_num` to check whether the operand can be
popped or not. While `loader_ctx->stack_cell_num` is updated in the
later `wasm_loader_push_pop_frame_ref`, the check may fail if the stack
is in polymorphic state and lead to `ctx->frame_offset` underflow.

Fix issue bytecodealliance#2577 and bytecodealliance#2586.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants