mimalloc icon indicating copy to clipboard operation
mimalloc copied to clipboard

Temporary `mi_heap` objects causing AddressSanitizer to report a buffer overrun on the TLD buffer upon calling `mi_heap_destroy`

Open XnLogicaL opened this issue 3 months ago • 1 comments

Summary

I am trying to wrap various mimalloc functions with a C++ class using mi_heap_t objects, however, upon calling mi_heap_destroy AddressSanitizer reports a buffer overrun on the TLD buffer associated with said mi_heap_t object. It appears that such behavior only occurs when mi_heap_destroy is called more than once within the lifetime of the program (even when called on distinct mi_heap_t objects).

(No multithreading involved, all behavior observed on T0)

Environment

  • OS: Ubuntu 24.04
  • CPU: Intel i9 i9900k [x86] (don't know if this is relevant or not)
  • Compiler: g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
  • Relevant compiler flags: -fsanitize=address,undefined,leak
  • Relevant linker flags: -fsanitize=address,undefined,leak
  • Active mimalloc commit hash: 09a2709

Minimal reproduction

Simple C++ class that wraps mi_heap_t (deleted move/copy semantics)

class Wrapper {
  mi_heap_t* heap;

  Wrapper() : heap(mi_heap_new()) {}
  ~Wrapper() { mi_heap_destroy(heap); }
}

Note that this simple reproduction snippet only appears to crash under specific conditions (that I am not able to observe), as opposed to a certain crash in a larger project that virtually implement mi_heap objects in the same way.

AddressSanitizer output:

=================================================================
==21152==ERROR: AddressSanitizer: global-buffer-overflow on address 0x74a5f71931a0 at pc 0x74a5f7118b16 bp 0x7ffce0d62ae0 sp 0x7ffce0d62ad0
READ of size 8 at 0x74a5f71931a0 thread T0
    #0 0x74a5f7118b15 in mi_stat_update /home/user/dev/via-lang/thirdparty/mimalloc/src/stats.c:41
    #1 0x74a5f7118f33 in _mi_stat_decrease /home/user/dev/via-lang/thirdparty/mimalloc/src/stats.c:61
    #2 0x74a5f710dd24 in mi_segment_page_clear /home/user/dev/via-lang/thirdparty/mimalloc/src/segment.c:1026
    #3 0x74a5f710e32b in _mi_segment_page_free /home/user/dev/via-lang/thirdparty/mimalloc/src/segment.c:1058
    #4 0x74a5f70d60d2 in _mi_heap_page_destroy /home/user/dev/via-lang/thirdparty/mimalloc/src/heap.c:365
    #5 0x74a5f70d342b in mi_heap_visit_pages /home/user/dev/via-lang/thirdparty/mimalloc/src/heap.c:46
    #6 0x74a5f70d610d in _mi_heap_destroy_pages /home/user/dev/via-lang/thirdparty/mimalloc/src/heap.c:371
    #7 0x74a5f70d633f in mi_heap_destroy /home/user/dev/via-lang/thirdparty/mimalloc/src/heap.c:405
    #8 0x56d8a2f8d3f4 in via::ScopedAllocator::~ScopedAllocator() /home/user/dev/via-lang/src/via-core/support/memory.h:201
    #9 0x56d8a30bb50a in via::VirtualMachine::~VirtualMachine() (/home/user/dev/via-lang/build/src/via-cli/via-cli+0x1a0350a) (BuildId: cd6ef4c17845494cec4d5aff0bee4566f2fb335b)
    #10 0x56d8a30b08b6 in via::Module::load_source_file(via::ModuleManager*, via::Module*, char const*, std::filesystem::__cxx11::path const&, via::ast::StmtImport const*, via::ModulePerms, via::ModuleFlags) /home/user/dev/via-lang/src/via-core/module/module.cpp:324
    #11 0x56d8a2f82f6e in main /home/user/dev/via-lang/src/via-cli/main.cpp:158
    #12 0x74a5f602a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #13 0x74a5f602a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #14 0x56d8a2f80974 in _start (/home/user/dev/via-lang/build/src/via-cli/via-cli+0x18c8974) (BuildId: cd6ef4c17845494cec4d5aff0bee4566f2fb335b)

0x74a5f71931a0 is located 16 bytes after global variable 'tld_main' defined in '/home/user/dev/via-lang/thirdparty/mimalloc/src/init.c:153:37' (0x74a5f7191d80) of size 5136
0x74a5f71931a0 is located 32 bytes before global variable '_mi_heap_main' defined in '/home/user/dev/via-lang/thirdparty/mimalloc/src/init.c:160:31' (0x74a5f71931c0) of size 3088
SUMMARY: AddressSanitizer: global-buffer-overflow /home/user/dev/via-lang/thirdparty/mimalloc/src/stats.c:41 in mi_stat_update
Shadow bytes around the buggy address:
  0x74a5f7192f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7192f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x74a5f7193180: 00 00 f9 f9[f9]f9 f9 f9 00 00 00 00 00 00 00 00
  0x74a5f7193200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x74a5f7193400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==21152==ABORTING

Notes

I am not familiar with the internals/footguns of mimalloc, so if I am misusing something please let me know. But from what I understand, such behavior is not intended.

Thanks in advance!

XnLogicaL avatar Sep 28 '25 10:09 XnLogicaL

Here are some similar issues (that I was able to find) that follow the same pattern but appear to occur under totally distinct circumstances: #1124 #1055

XnLogicaL avatar Sep 28 '25 10:09 XnLogicaL