From d9def29fe0dc8fc70ef270dcc1a266ad9257ec1f Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Mon, 14 Oct 2013 11:13:54 +0000 Subject: [ASan] Don't die with internal ASan error on large buffer overflows Summary: Out-of-bound access may touch not-yet allocated or already freed and recycled from quarantine chunks. We should treat this situation as a "free-range memory access" and avoid printing any data about that irrelevant chunk (which may be inconsistent). This should fix https://code.google.com/p/address-sanitizer/issues/detail?id=183 Reviewers: kcc Reviewed By: kcc CC: timurrrr, llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1893 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@192581 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_allocator.h | 9 +++++---- lib/asan/asan_allocator2.cc | 8 +++++--- lib/asan/asan_report.cc | 8 ++++++-- .../lit_tests/TestCases/heap-overflow-large.cc | 23 ++++++++++++++++++++++ lib/asan/lit_tests/TestCases/null_deref.cc | 2 +- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 lib/asan/lit_tests/TestCases/heap-overflow-large.cc diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index f817ce35..2591bc1b 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -35,10 +35,11 @@ void InitializeAllocator(); class AsanChunkView { public: explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} - bool IsValid() { return chunk_ != 0; } - uptr Beg(); // first byte of user memory. - uptr End(); // last byte of user memory. - uptr UsedSize(); // size requested by the user. + bool IsValid(); // Checks if AsanChunkView points to a valid allocated + // or quarantined chunk. + uptr Beg(); // First byte of user memory. + uptr End(); // Last byte of user memory. + uptr UsedSize(); // Size requested by the user. uptr AllocTid(); uptr FreeTid(); void GetAllocStack(StackTrace *stack); diff --git a/lib/asan/asan_allocator2.cc b/lib/asan/asan_allocator2.cc index 1a028d49..09ec1376 100644 --- a/lib/asan/asan_allocator2.cc +++ b/lib/asan/asan_allocator2.cc @@ -218,6 +218,9 @@ struct AsanChunk: ChunkBase { } }; +bool AsanChunkView::IsValid() { + return chunk_ != 0 && chunk_->chunk_state != CHUNK_AVAILABLE; +} uptr AsanChunkView::Beg() { return chunk_->Beg(); } uptr AsanChunkView::End() { return Beg() + UsedSize(); } uptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); } @@ -228,9 +231,8 @@ static void GetStackTraceFromId(u32 id, StackTrace *stack) { CHECK(id); uptr size = 0; const uptr *trace = StackDepotGet(id, &size); - CHECK_LT(size, kStackTraceMax); - internal_memcpy(stack->trace, trace, sizeof(uptr) * size); - stack->size = size; + CHECK(trace); + stack->CopyFrom(trace, size); } void AsanChunkView::GetAllocStack(StackTrace *stack) { diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 6a688452..864c3e96 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -414,7 +414,11 @@ static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, void DescribeHeapAddress(uptr addr, uptr access_size) { AsanChunkView chunk = FindHeapChunkByAddress(addr); - if (!chunk.IsValid()) return; + if (!chunk.IsValid()) { + Printf("AddressSanitizer can not describe address in more detail " + "(wild memory access suspected).\n"); + return; + } DescribeAccessToHeapChunk(chunk, addr, access_size); CHECK(chunk.AllocTid() != kInvalidTid); asanThreadRegistry().CheckLocked(); @@ -564,9 +568,9 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { (void*)addr, (void*)pc, (void*)sp, (void*)bp, GetCurrentTidOrInvalid()); Printf("%s", d.EndWarning()); - Printf("AddressSanitizer can not provide additional info.\n"); GET_STACK_TRACE_FATAL(pc, bp); PrintStack(&stack); + Printf("AddressSanitizer can not provide additional info.\n"); ReportSummary("SEGV", &stack); } diff --git a/lib/asan/lit_tests/TestCases/heap-overflow-large.cc b/lib/asan/lit_tests/TestCases/heap-overflow-large.cc new file mode 100644 index 00000000..67e9c371 --- /dev/null +++ b/lib/asan/lit_tests/TestCases/heap-overflow-large.cc @@ -0,0 +1,23 @@ +// Regression test for +// https://code.google.com/p/address-sanitizer/issues/detail?id=183 + +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: not %t 12 2>&1 | FileCheck %s +// RUN: not %t 100 2>&1 | FileCheck %s +// RUN: not %t 10000 2>&1 | FileCheck %s + +#include +#include + +int main(int argc, char *argv[]) { + int *x = new int[5]; + memset(x, 0, sizeof(x[0]) * 5); + int index = atoi(argv[1]); + int res = x[index]; + // CHECK: AddressSanitizer: {{(heap-buffer-overflow|SEGV)}} + // CHECK: #0 0x{{.*}} in main {{.*}}heap-overflow-large.cc:[[@LINE-2]] + // CHECK: AddressSanitizer can not {{(provide additional info|describe address in more detail \(wild memory access suspected\))}} + // CHECK: SUMMARY: AddressSanitizer: {{(heap-buffer-overflow|SEGV)}} + delete[] x; + return res; +} diff --git a/lib/asan/lit_tests/TestCases/null_deref.cc b/lib/asan/lit_tests/TestCases/null_deref.cc index 45296169..da0ca4be 100644 --- a/lib/asan/lit_tests/TestCases/null_deref.cc +++ b/lib/asan/lit_tests/TestCases/null_deref.cc @@ -11,7 +11,6 @@ __attribute__((noinline)) static void NullDeref(int *ptr) { // CHECK: ERROR: AddressSanitizer: SEGV on unknown address // CHECK: {{0x0*00028 .*pc 0x.*}} - // CHECK: {{AddressSanitizer can not provide additional info.}} ptr[10]++; // BOOM // atos on Mac cannot extract the symbol name correctly. // CHECK-Linux: {{ #0 0x.* in NullDeref.*null_deref.cc:}}[[@LINE-2]] @@ -20,4 +19,5 @@ static void NullDeref(int *ptr) { int main() { NullDeref((int*)0); // CHECK: {{ #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]] + // CHECK: {{AddressSanitizer can not provide additional info.}} } -- cgit v1.2.3