microsoft / mimalloc

mimalloc is a compact general purpose allocator with excellent performance.
MIT License
9.74k stars 793 forks source link

ASAN crash in `mi_checked_ptr_segment` when freeing memory from `abi::__cxa_demangle` #845

Open 0xjc opened 5 months ago

0xjc commented 5 months ago

Version: mimalloc v2.1.2 Mode: Static linking, override, ASAN OS: Linux (RHEL 7.9.2009) Compiler: GCC 10.3.0

Minimal repro:

mimalloc built with: cmake3 .. -DCMAKE_BUILD_TYPE=Debug -DMI_TRACK_ASAN=ON

Source code testing.cpp

#include <cxxabi.h>
#include <cstdlib>

int main() {
  int status = 0;
  char* const readable_name = abi::__cxa_demangle("FivE", 0, 0, &status);
  free(readable_name);
  return status;
}

Compile with:

g++-10.3 -ggdb3 -Wall mimalloc-asan-debug.o testing.cpp -otesting -fsanitize=address -lpthread

Execution result:

$ ./testing
mimalloc: warning: mi_free: pointer might not point to a valid heap region: 0x602000000010
(this may still be a valid very large allocation (over 64MiB))
=================================================================
==599==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000d8 at pc 0x000000408002 bp 0x7ffc163fb3c0 sp 0x7ffc163fb3b8
READ of size 8 at 0x6020000000d8 thread T0
    #0 0x408001 in mi_checked_ptr_segment [...]/mimalloc/src/alloc.c:543
    #1 0x40815d in mi_free [...]/mimalloc/src/alloc.c:564
    #2 0x404f7e in free [...]/mimalloc/src/alloc-override.c:135
    #3 0x43c0ff in main [...]/mimalloc/build-asan-debug/testing.cpp:7
    #4 0x7f8ca61b2554 in __libc_start_main (/lib64/libc.so.6+0x22554)
    #5 0x4023a8  (/var[...]/mimalloc/build-asan-debug/testing+0x4023a8)

Address 0x6020000000d8 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow [...]/mimalloc/src/alloc.c:543 in mi_checked_ptr_segment
Shadow bytes around the buggy address:
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff8000: fa fa 00 fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa[fa]fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8060: 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
  Shadow gap:              cc
==599==ABORTING

I noticed that when running under gdb, it appears that there is a call to realloc that does not go through mi_realloc.

#0  __interceptor_realloc (ptr=0x0, size=8) at ../../../../../src/gcc-10.3.0/libsanitizer/asan/asan_malloc_linux.cpp:38
#1  0x00007ffff7eb4d53 in d_growable_string_resize (need=<optimized out>, dgs=0x7fffffffbb40) at cp-demangle.c:4036
#2  d_growable_string_append_buffer (l=6, s=0x7fffffffb980 "int ()", dgs=0x7fffffffbb40) at cp-demangle.c:4060
#3  d_growable_string_callback_adapter (s=0x7fffffffb980 "int ()", l=6, opaque=0x7fffffffbb40) at cp-demangle.c:4077
#4  0x00007ffff7ebd1f0 in d_print_flush (dpi=0x7fffffffb980) at cp-demangle.c:4282
#5  d_print_callback (options=17, opaque=0x7fffffffbb40, callback=0x7ffff7eb4cd0 <d_growable_string_callback_adapter>, dc=0x7fffffffb860) at cp-demangle.c:4368
#6  d_demangle_callback (mangled=<optimized out>, callback=callback@entry=0x7ffff7eb4cd0 <d_growable_string_callback_adapter>, opaque=opaque@entry=0x7fffffffbb40, options=17) at cp-demangle.c:6358
#7  0x00007ffff7ebd9bd in d_demangle (options=17, palc=<synthetic pointer>, mangled=<optimized out>) at cp-demangle.c:6380
#8  __cxa_demangle (mangled_name=<optimized out>, output_buffer=0x0, length=0x0, status=0x7fffffffbbc0) at cp-demangle.c:6444
#9  0x000000000043c0f0 in main () at testing.cpp:6

However: