Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Double Free or Corruption Error on Valid WebAssembly Module Load #2586

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

Double Free or Corruption Error on Valid WebAssembly Module Load #2586

khagankhan opened this issue Sep 22, 2023 · 2 comments

Comments

@khagankhan
Copy link

Describe the Bug

When executing a valid WebAssembly module using the iwasm, the program terminates with a "double free or corruption" error, probably originating from the wasm_loader_ctx_destroy function in wasm_loader.c.

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 abort.

Files that cause the abort:

crash.wat.txt (Remove .txt extension when to save)

crash.wasm.txt (Remove .txt extension when to save)

Observed Behavior:

iwasm crash.wasm 

double free or corruption (out)
Aborted

Expected behavior:

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

GDB Backtrace

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737350600640) at ./nptl/pthread_kill.c:44
44	./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737350600640)
    at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737350600640) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737350600640, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7ce5476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff7ccb7f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7d2c6f6 in __libc_message (action=action@entry=do_abort, 
    fmt=fmt@entry=0x7ffff7e7eb8c "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#6  0x00007ffff7d43d7c in malloc_printerr (
    str=str@entry=0x7ffff7e817b0 "double free or corruption (out)") at ./malloc/malloc.c:5664
#7  0x00007ffff7d45ef0 in _int_free (av=0x7ffff7ebcc80 <main_arena>, p=0x55555588a2f0, 
    have_lock=<optimized out>) at ./malloc/malloc.c:4588
#8  0x00007ffff7d484d3 in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3391
#9  0x000055555557fd09 in wasm_runtime_free_internal (ptr=<optimized out>)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/common/wasm_memory.c:233
#10 wasm_runtime_free (ptr=<optimized out>)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/common/wasm_memory.c:265
#11 0x00005555555eb16b in wasm_loader_ctx_destroy (ctx=ctx@entry=0x555555889f50)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:5333
#12 0x0000555555615f95 in wasm_loader_prepare_bytecode (error_buf_size=<optimized out>, 
    error_buf=<optimized out>, cur_func_idx=<optimized out>, func=<optimized out>, 
    module=<optimized out>)
    at /root/wasmoi/wasm-micro-runtime/core/iwasm/interpreter/wasm_loader.c:10129

Reduced code that caused the abort (cat crash.wat):

(module
  (type (;0;) (func (param i64 f32 f32) (result i32)))
  (type (;1;) (func (param i64) (result i32)))
  (func (;0;) (type 0) (param i64 f32 f32) (result i32)
    (local i32 i64 f32 f64)
    global.get 0
    i32.const 0
    if (result i32) ;; label = @1
      i32.const 1
    else
      i32.const 0
      br 0 (;@1;)
      global.get 0
      i32.add
    end
    br_if 0 (;@0;)
    drop
    local.get 4
    i32.const 0
    call_indirect (type 1)
  )
  (table (;0;) 2 funcref)
  (global (;0;) (mut i32) i32.const 0)

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants