microsoft / microsoft/mimalloc

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

Open
#845 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
13.4k
Forks
1.2k
Avg merge
4d 45m
Merged PRs (30d)
13

Description

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
#include

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=, 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 , dc=0x7fffffffb860) at cp-demangle.c:4368
#6 d_demangle_callback (mangled=, callback=callback@entry=0x7ffff7eb4cd0 , opaque=opaque@entry=0x7fffffffbb40, options=17) at cp-demangle.c:6358
#7 0x00007ffff7ebd9bd in d_demangle (options=17, palc=, mangled=) at cp-demangle.c:6380
#8 __cxa_demangle (mangled_name=, output_buffer=0x0, length=0x0, status=0x7fffffffbbc0) at cp-demangle.c:6444
#9 0x000000000043c0f0 in main () at testing.cpp:6
```

However:
- If I compile without ASAN, I see this call go through `mi_realloc` as expected.
- If I call `realloc()` manually instead of through `abi::__cxa_demangle`, the call goes through `mi_realloc` as expected.

Contributor guide

No contributing guide indexed for this repository

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

Reproduce the ASAN failure using testing.cpp and the stated CMake build, then inspect src/alloc.c:543 and src/alloc-override.c:135 alongside the __cxa_demangle realloc stack. Compare the ASAN and non-ASAN paths to identify why the allocation bypasses mi_realloc. Done means the reproducer no longer crashes under ASAN and the relevant behavior is covered by a regression check.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cmake, linux
Domain
operating-systems, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.