| Título | WebAssembly wabt 1.0.39 and master-branch Use After Free |
|---|
| Descrição | Heap-use-after-free in InsertNode due to unsafe node erasure
### Description
We encountered a Heap-use-after-free (UAF) vulnerability in the wasm-decompile tool of the WABT project. The crash occurs during the decompilation process when wabt::AST::InsertNode attempts to read from a memory region that has already been freed.
Difference from CVE-2025-15411: Please note that this issue is fundamentally different from the previously reported heap-buffer-overflow (CVE-2025-15411) in the same function.
CVE-2025-15411 was caused by std::vector reallocation (_M_realloc_insert), invalidating pointers due to container resizing.
This Issue is caused by the explicit erasure of a node (_M_erase) from an associative container (Red-Black Tree, likely std::map or std::set), indicating a logical error in object lifecycle management.
### Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
- Build Command:
```
make clang-release-asan CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Release -DUSE_ASAN=ON -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG"
```
### Vulnerability Details
- Target: wasm-decompile
- Crash Type: Heap-use-after-free (CWE-416)
- Faulting Instruction: READ of size 8
- Location: wabt::AST::InsertNode (wasm-decompile+0x1c0949)
- Root Cause Analysis: The ASan report confirms a classic Use-After-Free scenario triggered by the explicit destruction of an object that is still referenced:
Allocation: Memory was allocated by operator new via std::_Rb_tree..._M_insert_range_unique. This confirms the object was stored in a Red-Black Tree structure (Map or Set).
Free (The Key Differentiator): The memory was subsequently freed by operator delete in ProgramMain -> std::_Rb_tree..._M_erase. This indicates an explicit removal operation.
Use: The freed memory was later accessed by wabt::AST::InsertNode during wabt::Decompiler::Decompile.
The stack trace demonstrates that the AST construction logic holds a dangling pointer to a node that was removed from its container in the main program flow.
### Reproduce
```
./wasm-decompile ./repro
```
Download Link: [repro](https://github.com/oneafter/1205/blob/main/af6)
ASAN report
```
==65817==ERROR: AddressSanitizer: heap-use-after-free on address 0x504000000a20 at pc 0x56263508594a bp 0x7ffc2d924fe0 sp 0x7ffc2d924fd8
READ of size 8 at 0x504000000a20 thread T0
#0 0x562635085949 in wabt::AST::InsertNode(wabt::NodeType, wabt::ExprType, wabt::Expr const*, unsigned int) (/src/repro/wabt/bin/wasm-decompile+0x1c0949) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#1 0x56263507c83a in wabt::AST::Construct(wabt::intrusive_list<wabt::Expr> const&, unsigned int, unsigned int, bool) (/src/repro/wabt/bin/wasm-decompile+0x1b783a) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#2 0x5626350774f1 in wabt::Decompiler::Decompile[abi:cxx11]() (/src/repro/wabt/bin/wasm-decompile+0x1b24f1) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#3 0x5626350752a6 in wabt::Decompile[abi:cxx11](wabt::Module const&, wabt::DecompileOptions const&) (/src/repro/wabt/bin/wasm-decompile+0x1b02a6) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#4 0x562635011941 in ProgramMain(int, char**) (/src/repro/wabt/bin/wasm-decompile+0x14c941) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#5 0x7ff08f0ef1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#6 0x7ff08f0ef28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#7 0x562634f35584 in _start (/src/repro/wabt/bin/wasm-decompile+0x70584) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
0x504000000a20 is located 16 bytes inside of 48-byte region [0x504000000a10,0x504000000a40)
freed by thread T0 here:
#0 0x56263500f271 in operator delete(void*) (/src/repro/wabt/bin/wasm-decompile+0x14a271) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#1 0x5626350794ef in std::_Rb_tree<std::basic_string_view<char, std::char_traits<char>>, std::basic_string_view<char, std::char_traits<char>>, std::_Identity<std::basic_string_view<char, std::char_traits<char>>>, std::less<std::basic_string_view<char, std::char_traits<char>>>, std::allocator<std::basic_string_view<char, std::char_traits<char>>>>::_M_erase(std::_Rb_tree_node<std::basic_string_view<char, std::char_traits<char>>>*) (/src/repro/wabt/bin/wasm-decompile+0x1b44ef) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#2 0x562635011919 in ProgramMain(int, char**) (/src/repro/wabt/bin/wasm-decompile+0x14c919) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#3 0x7ff08f0ef1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#4 0x7ff08f0ef28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#5 0x562634f35584 in _start (/src/repro/wabt/bin/wasm-decompile+0x70584) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
previously allocated by thread T0 here:
#0 0x56263500e9f1 in operator new(unsigned long) (/src/repro/wabt/bin/wasm-decompile+0x1499f1) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
#1 0x56263509d8a0 in std::enable_if<__same_value_type<std::basic_string_view<char, std::char_traits<char>> const*>::value, void>::type std::_Rb_tree<std::basic_string_view<char, std::char_traits<char>>, std::basic_string_view<char, std::char_traits<char>>, std::_Identity<std::basic_string_view<char, std::char_traits<char>>>, std::less<std::basic_string_view<char, std::char_traits<char>>>, std::allocator<std::basic_string_view<char, std::char_traits<char>>>>::_M_insert_range_unique<std::basic_string_view<char, std::char_traits<char>> const*>(std::basic_string_view<char, std::char_traits<char>> const*, std::basic_string_view<char, std::char_traits<char>> const*) (/src/repro/wabt/bin/wasm-decompile+0x1d88a0) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974)
SUMMARY: AddressSanitizer: heap-use-after-free (/src/repro/wabt/bin/wasm-decompile+0x1c0949) (BuildId: b44cadef6a2094e740cb6ce71ee9a45cfac22974) in wabt::AST::InsertNode(wabt::NodeType, wabt::ExprType, wabt::Expr const*, unsigned int)
Shadow bytes around the buggy address:
0x504000000780: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
0x504000000800: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
0x504000000880: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
0x504000000900: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
0x504000000980: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
=>0x504000000a00: fa fa fd fd[fd]fd fd fd fa fa 00 00 00 00 00 00
0x504000000a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000000c80: 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
==65817==ABORTING
``` |
|---|
| Fonte | ⚠️ https://github.com/WebAssembly/wabt/issues/2676 |
|---|
| Utilizador | Oneafter (UID 92781) |
|---|
| Submissão | 12/01/2026 03h16 (há 9 meses) |
|---|
| Moderação | 18/01/2026 21h28 (7 days later) |
|---|
| Estado | Duplicado |
|---|
| Entrada VulDB | 339332 [WebAssembly wabt até 1.0.39 wasm-decompile wabt::AST::InsertNode Excesso de tampão] |
|---|
| Pontos | 0 |
|---|