[asan] Fix internal CHECK failure on double free in recovery mode.
This patches fixes https://github.com/google/sanitizers/issues/639 Differential Revision: http://reviews.llvm.org/D15807 llvm-svn: 259473
This commit is contained in:
parent
05aecba118
commit
4a3c7fa441
|
|
@ -457,18 +457,25 @@ struct Allocator {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AtomicallySetQuarantineFlag(AsanChunk *m, void *ptr,
|
// Set quarantine flag if chunk is allocated, issue ASan error report on
|
||||||
|
// available and quarantined chunks. Return true on success, false otherwise.
|
||||||
|
bool AtomicallySetQuarantineFlagIfAllocated(AsanChunk *m, void *ptr,
|
||||||
BufferedStackTrace *stack) {
|
BufferedStackTrace *stack) {
|
||||||
u8 old_chunk_state = CHUNK_ALLOCATED;
|
u8 old_chunk_state = CHUNK_ALLOCATED;
|
||||||
// Flip the chunk_state atomically to avoid race on double-free.
|
// Flip the chunk_state atomically to avoid race on double-free.
|
||||||
if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state,
|
if (!atomic_compare_exchange_strong((atomic_uint8_t *)m, &old_chunk_state,
|
||||||
CHUNK_QUARANTINE, memory_order_acquire))
|
CHUNK_QUARANTINE,
|
||||||
|
memory_order_acquire)) {
|
||||||
ReportInvalidFree(ptr, old_chunk_state, stack);
|
ReportInvalidFree(ptr, old_chunk_state, stack);
|
||||||
|
// It's not safe to push a chunk in quarantine on invalid free.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
|
CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expects the chunk to already be marked as quarantined by using
|
// Expects the chunk to already be marked as quarantined by using
|
||||||
// AtomicallySetQuarantineFlag.
|
// AtomicallySetQuarantineFlagIfAllocated.
|
||||||
void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
|
void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
|
||||||
AllocType alloc_type) {
|
AllocType alloc_type) {
|
||||||
CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
|
CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
|
||||||
|
|
@ -522,7 +529,8 @@ struct Allocator {
|
||||||
}
|
}
|
||||||
ASAN_FREE_HOOK(ptr);
|
ASAN_FREE_HOOK(ptr);
|
||||||
// Must mark the chunk as quarantined before any changes to its metadata.
|
// Must mark the chunk as quarantined before any changes to its metadata.
|
||||||
AtomicallySetQuarantineFlag(m, ptr, stack);
|
// Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag.
|
||||||
|
if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return;
|
||||||
QuarantineChunk(m, ptr, stack, alloc_type);
|
QuarantineChunk(m, ptr, stack, alloc_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
// Also works if no malloc context is available.
|
// Also works if no malloc context is available.
|
||||||
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
|
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s
|
||||||
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
|
// RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
// RUN: %clangxx_asan -O0 -fsanitize-recover=address %s -o %t 2>&1
|
||||||
|
// RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix CHECK-RECOVER
|
||||||
|
|
||||||
// XFAIL: arm-linux-gnueabi
|
// XFAIL: arm-linux-gnueabi
|
||||||
// XFAIL: armv7l-unknown-linux-gnueabihf
|
// XFAIL: armv7l-unknown-linux-gnueabihf
|
||||||
|
|
||||||
|
|
@ -23,5 +27,7 @@ int main(int argc, char **argv) {
|
||||||
// MALLOC-CTX: #1 0x{{.*}} in main {{.*}}double-free.cc:[[@LINE-7]]
|
// MALLOC-CTX: #1 0x{{.*}} in main {{.*}}double-free.cc:[[@LINE-7]]
|
||||||
// CHECK: allocated by thread T0 here:
|
// CHECK: allocated by thread T0 here:
|
||||||
// MALLOC-CTX: double-free.cc:[[@LINE-12]]
|
// MALLOC-CTX: double-free.cc:[[@LINE-12]]
|
||||||
|
// CHECK-RECOVER: AddressSanitizer: attempting double-free{{.*}}in thread T0
|
||||||
|
// CHECK-RECOVER-NOT: AddressSanitizer CHECK failed:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue