summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-10-14 11:13:54 +0000
committerAlexey Samsonov <samsonov@google.com>2013-10-14 11:13:54 +0000
commitd9def29fe0dc8fc70ef270dcc1a266ad9257ec1f (patch)
tree7a9758d780cd7d8d20dbe07029bcd24d204b6443
parentfa33a8c89d3cb505c99a2d700a8c174a0ff4fb38 (diff)
downloadcompiler-rt-d9def29fe0dc8fc70ef270dcc1a266ad9257ec1f.tar.gz
compiler-rt-d9def29fe0dc8fc70ef270dcc1a266ad9257ec1f.tar.bz2
compiler-rt-d9def29fe0dc8fc70ef270dcc1a266ad9257ec1f.tar.xz
[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
-rw-r--r--lib/asan/asan_allocator.h9
-rw-r--r--lib/asan/asan_allocator2.cc8
-rw-r--r--lib/asan/asan_report.cc8
-rw-r--r--lib/asan/lit_tests/TestCases/heap-overflow-large.cc23
-rw-r--r--lib/asan/lit_tests/TestCases/null_deref.cc2
5 files changed, 40 insertions, 10 deletions
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 <stdlib.h>
+#include <string.h>
+
+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.}}
}