Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Double free for large allocation not detected, aborts due to invalid write #1502

Open
chrstphrchvz opened this issue Mar 22, 2022 · 0 comments

Comments

@chrstphrchvz
Copy link

chrstphrchvz commented Mar 22, 2022

I originally noticed this issue in a program with (unintentional) behavior equivalent to the following:

void *p, *q;
p = malloc(18);
p = realloc(p, 2147483658UL);
q = realloc(p, 0);
if (NULL == q)
	p = realloc(p, 0);

(I’m aware that realloc(p, 0) for non-NULL p is expected to become undefined behavior in C23.)

The allocator_frees_and_returns_null_on_realloc_zero flag being enabled by default means this example causes a double free; but ASan does not detect it, instead aborting due to an invalid write:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==29282==ERROR: AddressSanitizer: SEGV on unknown address 0xa4cff7f0 (pc 0xb79cfc7b bp 0xa4cff7f0 sp 0xbfd5af20 T0)
==29282==The signal is caused by a WRITE memory access.
    #0 0xb79cfc7b in bool __sanitizer::atomic_compare_exchange_strong<__sanitizer::atomic_uint8_t>(__sanitizer::atomic_uint8_t volatile*, __sanitizer::atomic_uint8_t::Type*, __sanitizer::atomic_uint8_t::Type, __sanitizer::memory_order) /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h:80
    #1 0xb79cfc7b in __asan::Allocator::AtomicallySetQuarantineFlagIfAllocated(__asan::AsanChunk*, void*, __sanitizer::BufferedStackTrace*) /usr/src/debug/gcc/libsanitizer/asan/asan_allocator.cpp:621
    #2 0xb79cfc7b in __asan::Allocator::Deallocate(void*, unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, __asan::AllocType) /usr/src/debug/gcc/libsanitizer/asan/asan_allocator.cpp:697
    #3 0xb79cfc7b in __asan::asan_realloc(void*, unsigned long, __sanitizer::BufferedStackTrace*) /usr/src/debug/gcc/libsanitizer/asan/asan_allocator.cpp:1003
    #4 0xb7a69e24 in __interceptor_realloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:165
    #5 0x4b9295 in main (/home/user/a.out+0x1295)
    #6 0xb77dc258 in __libc_start_call_main (/usr/lib/libc.so.6+0x25258)
    #7 0xb77dc333 in __libc_start_main_impl (/usr/lib/libc.so.6+0x25333)
    #8 0x4b90ea in _start (/home/user/a.out+0x10ea)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h:80 in bool __sanitizer::atomic_compare_exchange_strong<__sanitizer::atomic_uint8_t>(__sanitizer::atomic_uint8_t volatile*, __sanitizer::atomic_uint8_t::Type*, __sanitizer::atomic_uint8_t::Type, __sanitizer::memory_order)
==29282==ABORTING

The issue more generally seems to be that when doing void *p = malloc(s); free(p); free(p); for sufficiently large s (I’m not aware what determines the cutoff), ASan does not detect the double free, and an invalid write in ASan occurs instead. I observed this with both LLVM Clang 13.0.1 (still present in 17.0.1) on macOS and GCC 11.2.0 on Linux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant