Skip to content

[Segmentation fault] Out-of-bounds read from wasm::WATParser::assertAction #6872

@sofiaaberegg

Description

@sofiaaberegg

Hi,

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

Steps to reproduce:

Test file: wast-oob-read.zip
Command: ./wasm2js ./wast-oob-read.wast

GDB:

gdb --args ./wasm2js ./wast-oob-read.wast GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1 Reading symbols from ./wasm2js... (gdb) run Starting program: /home/sofi/binaryen-test/binaryen/bin/wasm2js ./wast-oob-read.wast [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Program received signal SIGSEGV, Segmentation fault. 0x00005555562d1e38 in std::__detail::__variant::__variant_construct<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&> (__lhs=..., __rhs=...) at /usr/include/c++/11/variant:499 499 __lhs._M_index = __rhs._M_index; (gdb) bt #0 0x00005555562d1e38 in std::__detail::__variant::__variant_construct<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&> (__lhs=..., __rhs=...) at /usr/include/c++/11/variant:499 #1 0x00005555562cd5e0 in std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_ctor_base (this=0x7fffffffc168, __rhs=...) at /usr/include/c++/11/variant:519 #2 0x00005555562cb53d in std::__detail::__variant::_Move_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_ctor_base (this=0x7fffffffc168) at /usr/include/c++/11/variant:566 #3 0x00005555562cb567 in std::__detail::__variant::_Copy_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_assign_base (this=0x7fffffffc168) at /usr/include/c++/11/variant:640 #4 0x00005555562cb591 in std::__detail::__variant::_Move_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_assign_base (this=0x7fffffffc168) at /usr/include/c++/11/variant:683 #5 0x00005555562cb5bb in std::__detail::__variant::_Variant_base<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Variant_base (this=0x7fffffffc168) at /usr/include/c++/11/variant:715 #6 0x00005555562cb5e5 in std::variant<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::variant ( this=0x7fffffffc168, __rhs=<error reading variable: Cannot access memory at address 0x60>...) at /usr/include/c++/11/variant:1396 #7 0x00005555562c77bb in wasm::WATParser::(anonymous namespace)::assertAction (in=...) at /home/sofi/binaryen-test/binaryen/src/parser/wast-parser.cpp:286 #8 0x00005555562c89eb in wasm::WATParser::(anonymous namespace)::assertion (in=...) at /home/sofi/binaryen-test/binaryen/src/parser/wast-parser.cpp:357 #9 0x00005555562c94e6 in wasm::WATParser::(anonymous namespace)::command (in=...) at /home/sofi/binaryen-test/binaryen/src/parser/wast-parser.cpp:402 #10 0x00005555562c98b0 in wasm::WATParser::(anonymous namespace)::wast (in=...) at /home/sofi/binaryen-test/binaryen/src/parser/wast-parser.cpp:418 #11 0x00005555562c9d2f in wasm::WATParser::parseScript ( in=" (assert_exhaustion \"even", '\263' <repeats 19 times>, "γ", '\263' <repeats 26 times>, "i32.ge_uqt !f\")\263\263\263\263\263\263\263\" (i32.const i31.subset_globalt $n) (i32.consti64.sub 1))))\nd (20\t) (i32.con32.const 1))\n (else (call"...) at /home/sofi/binaryen-test/binaryen/src/parser/wast-parser.cpp:443 #12 0x0000555555591a91 in main (argc=2, argv=0x7fffffffe068) at /home/sofi/binaryen-test/binaryen/src/tools/wasm2js.cpp:936 

Valgrind:

valgrind ./wasm2js ./wast-oob-read.wast ==3911616== Memcheck, a memory error detector ==3911616== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. ==3911616== Using Valgrind-3.24.0.GIT and LibVEX; rerun with -h for copyright info ==3911616== Command: ./wasm2js ./wast-oob-read.wast ==3911616== ==3911616== Invalid read of size 1 ==3911616== at 0xE85E38: void std::__detail::__variant::__variant_construct<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&>(std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:499) ==3911616== by 0xE815DF: std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_ctor_base(std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:519) ==3911616== by 0xE7F53C: std::__detail::__variant::_Move_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_ctor_base(std::__detail::__variant::_Move_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:566) ==3911616== by 0xE7F566: std::__detail::__variant::_Copy_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_assign_base(std::__detail::__variant::_Copy_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:640) ==3911616== by 0xE7F590: std::__detail::__variant::_Move_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_assign_base(std::__detail::__variant::_Move_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:683) ==3911616== by 0xE7F5BA: std::__detail::__variant::_Variant_base<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Variant_base(std::__detail::__variant::_Variant_base<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:715) ==3911616== by 0xE7F5E4: std::variant<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::variant(std::variant<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:1396) ==3911616== by 0xE7B7BA: wasm::WATParser::(anonymous namespace)::assertAction(wasm::WATParser::Lexer&) (wast-parser.cpp:286) ==3911616== by 0xE7C9EA: wasm::WATParser::(anonymous namespace)::assertion(wasm::WATParser::Lexer&) (wast-parser.cpp:357) ==3911616== by 0xE7D4E5: wasm::WATParser::(anonymous namespace)::command(wasm::WATParser::Lexer&) (wast-parser.cpp:402) ==3911616== by 0xE7D8AF: wasm::WATParser::(anonymous namespace)::wast(wasm::WATParser::Lexer&) (wast-parser.cpp:418) ==3911616== by 0xE7DD2E: wasm::WATParser::parseScript(std::basic_string_view<char, std::char_traits<char> >) (wast-parser.cpp:443) ==3911616== Address 0x60 is not stack'd, malloc'd or (recently) free'd ==3911616== ==3911616== ==3911616== Process terminating with default action of signal 11 (SIGSEGV) ==3911616== Access not within mapped region at address 0x60 ==3911616== at 0xE85E38: void std::__detail::__variant::__variant_construct<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&>(std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>&, std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:499) ==3911616== by 0xE815DF: std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_ctor_base(std::__detail::__variant::_Copy_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:519) ==3911616== by 0xE7F53C: std::__detail::__variant::_Move_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_ctor_base(std::__detail::__variant::_Move_ctor_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:566) ==3911616== by 0xE7F566: std::__detail::__variant::_Copy_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Copy_assign_base(std::__detail::__variant::_Copy_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:640) ==3911616== by 0xE7F590: std::__detail::__variant::_Move_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Move_assign_base(std::__detail::__variant::_Move_assign_base<false, wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:683) ==3911616== by 0xE7F5BA: std::__detail::__variant::_Variant_base<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::_Variant_base(std::__detail::__variant::_Variant_base<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:715) ==3911616== by 0xE7F5E4: std::variant<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction>::variant(std::variant<wasm::WATParser::InvokeAction, wasm::WATParser::GetAction> const&) (variant:1396) ==3911616== by 0xE7B7BA: wasm::WATParser::(anonymous namespace)::assertAction(wasm::WATParser::Lexer&) (wast-parser.cpp:286) ==3911616== by 0xE7C9EA: wasm::WATParser::(anonymous namespace)::assertion(wasm::WATParser::Lexer&) (wast-parser.cpp:357) ==3911616== by 0xE7D4E5: wasm::WATParser::(anonymous namespace)::command(wasm::WATParser::Lexer&) (wast-parser.cpp:402) ==3911616== by 0xE7D8AF: wasm::WATParser::(anonymous namespace)::wast(wasm::WATParser::Lexer&) (wast-parser.cpp:418) ==3911616== by 0xE7DD2E: wasm::WATParser::parseScript(std::basic_string_view<char, std::char_traits<char> >) (wast-parser.cpp:443) ==3911616== If you believe this happened as a result of a stack ==3911616== overflow in your program's main thread (unlikely but ==3911616== possible), you can try to increase the size of the ==3911616== main thread stack using the --main-stacksize= flag. ==3911616== The main thread stack size used in this run was 8388608. ==3911616== ==3911616== HEAP SUMMARY: ==3911616== in use at exit: 236,327 bytes in 2,252 blocks ==3911616== total heap usage: 3,631 allocs, 1,379 frees, 375,466 bytes allocated ==3911616== ==3911616== LEAK SUMMARY: ==3911616== definitely lost: 0 bytes in 0 blocks ==3911616== indirectly lost: 0 bytes in 0 blocks ==3911616== possibly lost: 0 bytes in 0 blocks ==3911616== still reachable: 236,327 bytes in 2,252 blocks ==3911616== suppressed: 0 bytes in 0 blocks ==3911616== Rerun with --leak-check=full to see details of leaked memory ==3911616== ==3911616== For lists of detected and suppressed errors, rerun with: -s ==3911616== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Segmentation fault 

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