[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

llvm-svn: 192581
This commit is contained in:
Alexey Samsonov 2013-10-14 11:13:54 +00:00
parent 421e884b31
commit df6e6569c0
5 changed files with 40 additions and 10 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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.}}
}