WebAssembly/binaryen

[Segmentation fault] Out-of-bounds read in wasm::HeapType::isBasic

sofiaaberegg opened this issue · 0 comments

Hi,

I identified an out-of-bounds data read bug when fuzzing the wasm-opt tool.

Steps to reproduce:

Test file: wast-oob-read.zip
Command: ./wasm-opt ./wast-oob-read.wast

GDB:

gdb --args ./wasm-opt ./wast-oob-read.wast 
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1

Reading symbols from ./wasm-opt...
(gdb) run
Starting program: /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/bin/wasm-opt ./wast-oob-read.wast
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff7600640 (LWP 907262)]
[New Thread 0x7ffff6c00640 (LWP 907263)]
[New Thread 0x7ffff6200640 (LWP 907264)]
[New Thread 0x7ffff5800640 (LWP 907265)]
[New Thread 0x7ffff4e00640 (LWP 907266)]
[New Thread 0x7ffff4400640 (LWP 907267)]
[New Thread 0x7ffff3a00640 (LWP 907268)]
[New Thread 0x7ffff3000640 (LWP 907269)]
[New Thread 0x7ffff2600640 (LWP 907270)]
[New Thread 0x7ffff1c00640 (LWP 907271)]
[New Thread 0x7ffff1200640 (LWP 907272)]
[New Thread 0x7ffff0800640 (LWP 907273)]
[New Thread 0x7fffefe00640 (LWP 907274)]
[New Thread 0x7fffef400640 (LWP 907275)]
[New Thread 0x7fffeea00640 (LWP 907276)]
[New Thread 0x7fffee000640 (LWP 907277)]
[New Thread 0x7fffed600640 (LWP 907278)]
[New Thread 0x7fffecc00640 (LWP 907279)]
[New Thread 0x7fffec200640 (LWP 907280)]
[New Thread 0x7fffeb800640 (LWP 907281)]
[New Thread 0x7fffeae00640 (LWP 907282)]
[New Thread 0x7fffea400640 (LWP 907283)]
[New Thread 0x7fffe9a00640 (LWP 907284)]
[New Thread 0x7fffe9000640 (LWP 907285)]

Thread 1 "wasm-opt" received signal SIGSEGV, Segmentation fault.
0x00005555555b80b2 in wasm::HeapType::isBasic (this=0x38) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm-type.h:378
378	  constexpr bool isBasic() const { return id <= _last_basic_type; }
(gdb) bt
#0  0x00005555555b80b2 in wasm::HeapType::isBasic (this=0x38) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm-type.h:378
#1  0x000055555616e814 in wasm::HeapType::getKind (this=0x38) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-type.cpp:1100
#2  0x00005555555b80da in wasm::HeapType::isSignature (this=0x38) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm-type.h:387
#3  0x000055555616e94e in wasm::HeapType::getSignature (this=0x38) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-type.cpp:1148
#4  0x00005555555ba11e in wasm::Function::getSig (this=0x0) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm.h:2091
#5  0x00005555555ba199 in wasm::Function::getResults (this=0x0) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm.h:2093
#6  0x00005555561ba2cf in wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call> (this=0x7fffffffb990, curr=0x555556f8ba60, sigType=..., printable=0x555556f8ba60)
    at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:609
#7  0x00005555561b1882 in wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call> (this=0x7fffffffb990, curr=0x555556f8ba60, sigType=...) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:626
#8  0x00005555561952da in wasm::FunctionValidator::visitCall (this=0x7fffffffb990, curr=0x555556f8ba60) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:941
#9  0x00005555561b7bfa in wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::doVisitCall (self=0x7fffffffb990, currp=0x7fffffffb910) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm-delegations.def:23
#10 0x00005555561adcc4 in wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::walk (this=0x7fffffffb9e8, root=@0x7fffffffb910: 0x555556f8ba60)
    at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm-traversal.h:307
#11 0x00005555561ac979 in wasm::FunctionValidator::validate (this=0x7fffffffb990, curr=0x555556f8ba60) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:261
#12 0x00005555561a0483 in operator() (__closure=0x7fffffffbc30, curr=0x555556f5d2e0) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:3781
#13 0x00005555561a3c5d in wasm::ModuleUtils::iterDefinedGlobals<wasm::validateGlobals(wasm::Module&, wasm::ValidationInfo&)::<lambda(wasm::Global*)> >(wasm::Module &, struct {...}) (wasm=..., visitor=...)
    at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/ir/module-utils.h:158
#14 0x00005555561a0741 in wasm::validateGlobals (module=..., info=...) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:3763
#15 0x00005555561a2f0f in wasm::WasmValidator::validate (this=0x7fffffffc2f0, module=..., flags=2) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:4159
#16 0x00005555561a32bd in wasm::WasmValidator::validate (this=0x7fffffffc2f0, module=..., options=...) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/wasm/wasm-validator.cpp:4192
#17 0x000055555565bdf3 in main (argc=2, argv=0x7fffffffe028) at /home/sofi/fuzzing/binaryen/executables/Debug/binaryen/src/tools/wasm-opt.cpp:298

Valgrind:


valgrind ./wasm-opt ./wast-oob-read.wast 
==908112== Memcheck, a memory error detector
==908112== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==908112== Using Valgrind-3.24.0.GIT and LibVEX; rerun with -h for copyright info
==908112== Command: ./wasm-opt ./wast-oob-read.wast
==908112== 
==908112== Invalid read of size 8
==908112==    at 0x16C0B2: wasm::HeapType::isBasic() const (wasm-type.h:378)
==908112==    by 0xD22813: wasm::HeapType::getKind() const (wasm-type.cpp:1100)
==908112==    by 0x16C0D9: wasm::HeapType::isSignature() const (wasm-type.h:387)
==908112==    by 0xD2294D: wasm::HeapType::getSignature() const (wasm-type.cpp:1148)
==908112==    by 0x16E11D: wasm::Function::getSig() (wasm.h:2091)
==908112==    by 0x16E198: wasm::Function::getResults() (wasm.h:2093)
==908112==    by 0xD6E2CE: void wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call>(wasm::Call*, wasm::HeapType, wasm::Expression*) (wasm-validator.cpp:609)
==908112==    by 0xD65881: void wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call>(wasm::Call*, wasm::HeapType) (wasm-validator.cpp:626)
==908112==    by 0xD492D9: wasm::FunctionValidator::visitCall(wasm::Call*) (wasm-validator.cpp:941)
==908112==    by 0xD6BBF9: wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::doVisitCall(wasm::FunctionValidator*, wasm::Expression**) (wasm-delegations.def:23)
==908112==    by 0xD61CC3: wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::walk(wasm::Expression*&) (wasm-traversal.h:307)
==908112==    by 0xD60978: wasm::FunctionValidator::validate(wasm::Expression*) (wasm-validator.cpp:261)
==908112==  Address 0x38 is not stack'd, malloc'd or (recently) free'd
==908112== 
==908112== 
==908112== Process terminating with default action of signal 11 (SIGSEGV)
==908112==  Access not within mapped region at address 0x38
==908112==    at 0x16C0B2: wasm::HeapType::isBasic() const (wasm-type.h:378)
==908112==    by 0xD22813: wasm::HeapType::getKind() const (wasm-type.cpp:1100)
==908112==    by 0x16C0D9: wasm::HeapType::isSignature() const (wasm-type.h:387)
==908112==    by 0xD2294D: wasm::HeapType::getSignature() const (wasm-type.cpp:1148)
==908112==    by 0x16E11D: wasm::Function::getSig() (wasm.h:2091)
==908112==    by 0x16E198: wasm::Function::getResults() (wasm.h:2093)
==908112==    by 0xD6E2CE: void wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call>(wasm::Call*, wasm::HeapType, wasm::Expression*) (wasm-validator.cpp:609)
==908112==    by 0xD65881: void wasm::FunctionValidator::validateCallParamsAndResult<wasm::Call>(wasm::Call*, wasm::HeapType) (wasm-validator.cpp:626)
==908112==    by 0xD492D9: wasm::FunctionValidator::visitCall(wasm::Call*) (wasm-validator.cpp:941)
==908112==    by 0xD6BBF9: wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::doVisitCall(wasm::FunctionValidator*, wasm::Expression**) (wasm-delegations.def:23)
==908112==    by 0xD61CC3: wasm::Walker<wasm::FunctionValidator, wasm::Visitor<wasm::FunctionValidator, void> >::walk(wasm::Expression*&) (wasm-traversal.h:307)
==908112==    by 0xD60978: wasm::FunctionValidator::validate(wasm::Expression*) (wasm-validator.cpp:261)
==908112==  If you believe this happened as a result of a stack
==908112==  overflow in your program's main thread (unlikely but
==908112==  possible), you can try to increase the size of the
==908112==  main thread stack using the --main-stacksize= flag.
==908112==  The main thread stack size used in this run was 8388608.
==908112== 
==908112== HEAP SUMMARY:
==908112==     in use at exit: 262,200 bytes in 2,055 blocks
==908112==   total heap usage: 3,648 allocs, 1,593 frees, 411,706 bytes allocated
==908112== 
==908112== LEAK SUMMARY:
==908112==    definitely lost: 0 bytes in 0 blocks
==908112==    indirectly lost: 0 bytes in 0 blocks
==908112==      possibly lost: 7,296 bytes in 24 blocks
==908112==    still reachable: 254,904 bytes in 2,031 blocks
==908112==         suppressed: 0 bytes in 0 blocks
==908112== Rerun with --leak-check=full to see details of leaked memory
==908112== 
==908112== For lists of detected and suppressed errors, rerun with: -s
==908112== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault