Skip to content

Commit

Permalink
[asan] Fix internal CHECK failure on double free in recovery mode.
Browse files Browse the repository at this point in the history
This patches fixes google/sanitizers#639

Differential Revision: http://reviews.llvm.org/D15807

llvm-svn: 259473
  • Loading branch information
Maxim Ostapenko committed Feb 2, 2016
1 parent 05aecba commit 4a3c7fa
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 5 deletions.
18 changes: 13 additions & 5 deletions compiler-rt/lib/asan/asan_allocator.cc
Expand Up @@ -457,18 +457,25 @@ struct Allocator {
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) {
u8 old_chunk_state = CHUNK_ALLOCATED;
// Flip the chunk_state atomically to avoid race on double-free.
if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state,
CHUNK_QUARANTINE, memory_order_acquire))
if (!atomic_compare_exchange_strong((atomic_uint8_t *)m, &old_chunk_state,
CHUNK_QUARANTINE,
memory_order_acquire)) {
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);
return true;
}

// Expects the chunk to already be marked as quarantined by using
// AtomicallySetQuarantineFlag.
// AtomicallySetQuarantineFlagIfAllocated.
void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
AllocType alloc_type) {
CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
Expand Down Expand Up @@ -522,7 +529,8 @@ struct Allocator {
}
ASAN_FREE_HOOK(ptr);
// 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);
}

Expand Down
6 changes: 6 additions & 0 deletions compiler-rt/test/asan/TestCases/double-free.cc
Expand Up @@ -4,6 +4,10 @@
// 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=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: armv7l-unknown-linux-gnueabihf

Expand All @@ -23,5 +27,7 @@ int main(int argc, char **argv) {
// MALLOC-CTX: #1 0x{{.*}} in main {{.*}}double-free.cc:[[@LINE-7]]
// CHECK: allocated by thread T0 here:
// MALLOC-CTX: double-free.cc:[[@LINE-12]]
// CHECK-RECOVER: AddressSanitizer: attempting double-free{{.*}}in thread T0
// CHECK-RECOVER-NOT: AddressSanitizer CHECK failed:
return res;
}

0 comments on commit 4a3c7fa

Please sign in to comment.