WebAssembly / WebAssembly/wabt

heap overflow in wabt::Node::operator=(wabt::Node&&)

Open
#1,989 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

sanitizer failures
Dominant language
C++
Stars
8.1k
Forks
827
Avg merge
4d 6h
Merged PRs (30d)
18

Description

Environment
OS      : Linux ubuntu 5.15.0-46-generic #49~20.04.1-Ubuntu SMP Thu Aug 4 19:15:44 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Commit  : 3054d61f703d609995798f872fc86b462617c294
Version : 1.0.29
Build   : make clang-debug-asan
Proof of concept

poc-2.wasm.zip

Stack dump
=================================================================
==1704949==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x610000000010 at pc 0x0000005f2828 bp 0x7ffc769a3c60 sp 0x7ffc769a3c58
READ of size 4 at 0x610000000010 thread T0
    #0 0x5f2827 in wabt::Node::operator=(wabt::Node&&) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:67:17
    #1 0x5dc955 in wabt::Node::Node(wabt::Node&&) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:65:28
    #2 0x5f54b0 in std::enable_if<__and_<std::__not_<std::__is_tuple_like<wabt::Node>>, std::is_move_constructible<wabt::Node>, std::is_move_assignable<wabt::Node>>::value, void>::type std::swap<wabt::Node>(wabt::Node&, wabt::Node&) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/move.h:197:19
    #3 0x5f501e in void std::iter_swap<__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>>(__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_algobase.h:182:7
    #4 0x5f46ed in __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>> std::_V2::__rotate<__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>>(__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, std::random_access_iterator_tag) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_algo.h:1394:5
    #5 0x5dd60f in __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>> std::_V2::rotate<__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>>(__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, __gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_algo.h:1439:14
    #6 0x5dd066 in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool)::'lambda'(unsigned long)::operator()(unsigned long) const /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:279:11
    #7 0x5c8556 in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:307:13
    #8 0x5ee577 in void wabt::AST::Block<(wabt::ExprType)8>(wabt::BlockExprBase<(wabt::ExprType)8> const&, wabt::LabelType) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:159:5
    #9 0x5dc2fd in wabt::AST::Construct(wabt::Expr const&) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:212:9
    #10 0x5c7b64 in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:248:7
    #11 0x5c281f in wabt::Decompiler::Decompile[abi:cxx11]() /wabt/out/clang/Debug/asan/../../../../src/decompiler.cc:795:13
    #12 0x5be6bd in wabt::Decompile[abi:cxx11](wabt::Module const&, wabt::DecompileOptions const&) /wabt/out/clang/Debug/asan/../../../../src/decompiler.cc:854:21
    #13 0x4f16bd in ProgramMain(int, char**) /wabt/out/clang/Debug/asan/../../../../src/tools/wasm-decompile.cc:103:18
    #14 0x4f2101 in main /wabt/out/clang/Debug/asan/../../../../src/tools/wasm-decompile.cc:116:10
    #15 0x7f9cae44d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #16 0x43f04d in _start (/wabt/out/clang/Debug/asan/wasm-decompile+0x43f04d)

0x610000000010 is located 48 bytes to the left of 192-byte region [0x610000000040,0x610000000100)
allocated by thread T0 here:
    #0 0x4edc5d in operator new(unsigned long) /home/build-user/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3
    #1 0x5f05c8 in __gnu_cxx::new_allocator<wabt::Node>::allocate(unsigned long, void const*) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:115:27
    #2 0x5f0570 in std::allocator_traits<std::allocator<wabt::Node>>::allocate(std::allocator<wabt::Node>&, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:460:20
    #3 0x5effaf in std::_Vector_base<wabt::Node, std::allocator<wabt::Node>>::_M_allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:346:20
    #4 0x5f3462 in void std::vector<wabt::Node, std::allocator<wabt::Node>>::_M_realloc_insert<wabt::Node>(__gnu_cxx::__normal_iterator<wabt::Node*, std::vector<wabt::Node, std::allocator<wabt::Node>>>, wabt::Node&&) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/vector.tcc:440:33
    #5 0x5f3124 in wabt::Node& std::vector<wabt::Node, std::allocator<wabt::Node>>::emplace_back<wabt::Node>(wabt::Node&&) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/vector.tcc:121:4
    #6 0x5dcbdc in std::vector<wabt::Node, std::allocator<wabt::Node>>::push_back(wabt::Node&&) /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:1204:9
    #7 0x5de429 in wabt::AST::InsertNode(wabt::NodeType, wabt::ExprType, wabt::Expr const*, unsigned int) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:104:15
    #8 0x5dc5d0 in wabt::AST::Construct(wabt::Expr const&) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:230:9
    #9 0x5c7b64 in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:248:7
    #10 0x5ee577 in void wabt::AST::Block<(wabt::ExprType)8>(wabt::BlockExprBase<(wabt::ExprType)8> const&, wabt::LabelType) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:159:5
    #11 0x5dc2fd in wabt::AST::Construct(wabt::Expr const&) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:212:9
    #12 0x5c7b64 in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool) /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:248:7
    #13 0x5c281f in wabt::Decompiler::Decompile[abi:cxx11]() /wabt/out/clang/Debug/asan/../../../../src/decompiler.cc:795:13
    #14 0x5be6bd in wabt::Decompile[abi:cxx11](wabt::Module const&, wabt::DecompileOptions const&) /wabt/out/clang/Debug/asan/../../../../src/decompiler.cc:854:21
    #15 0x4f16bd in ProgramMain(int, char**) /wabt/out/clang/Debug/asan/../../../../src/tools/wasm-decompile.cc:103:18
    #16 0x4f2101 in main /wabt/out/clang/Debug/asan/../../../../src/tools/wasm-decompile.cc:116:10
    #17 0x7f9cae44d082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /wabt/out/clang/Debug/asan/../../../../src/decompiler-ast.h:67:17 in wabt::Node::operator=(wabt::Node&&)
Shadow bytes around the buggy address:
  0x0c207fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c207fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c207fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c207fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c207fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c207fff8000: fa fa[fa]fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c207fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c207fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c207fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c207fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c207fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==1704949==ABORTING

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/decompiler-ast.h at the reported Node move-assignment and AST::Construct locations, then reproduce the failure using wasm-decompile with poc-2.wasm under the make clang-debug-asan build. Trace the vector rotation path and verify that the proof of concept no longer triggers an AddressSanitizer heap-buffer-overflow.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, wasm
Domain
compilers, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.