[compiler-rt] r194579 - [ASan] Do not rely on malloc context in allocator reports.

Alexey Samsonov samsonov at google.com
Wed Nov 13 06:46:58 PST 2013


Author: samsonov
Date: Wed Nov 13 08:46:58 2013
New Revision: 194579

URL: http://llvm.org/viewvc/llvm-project?rev=194579&view=rev
Log:
[ASan] Do not rely on malloc context in allocator reports.

Invoke a fatal stack trace unwinder when ASan prints allocator-relevant
error reports (double-free, alloc-dealloc-mismatch, invalid-free).
Thus we'll be able to print complete stack trace even if allocation/free
stacks are not stored (malloc_context_size=0).

Based on the patch by Yuri Gribov!

Modified:
    compiler-rt/trunk/lib/asan/asan_allocator.h
    compiler-rt/trunk/lib/asan/asan_allocator2.cc
    compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
    compiler-rt/trunk/lib/asan/asan_malloc_win.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/double-free.cc
    compiler-rt/trunk/lib/asan/lit_tests/TestCases/invalid-free.cc
    compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.h?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.h (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.h Wed Nov 13 08:46:58 2013
@@ -115,7 +115,7 @@ void *asan_pvalloc(uptr size, StackTrace
 
 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
                           StackTrace *stack);
-uptr asan_malloc_usable_size(void *ptr, StackTrace *stack);
+uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp);
 
 uptr asan_mz_size(const void *ptr);
 void asan_mz_force_lock();

Modified: compiler-rt/trunk/lib/asan/asan_allocator2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator2.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator2.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator2.cc Wed Nov 13 08:46:58 2013
@@ -664,12 +664,13 @@ int asan_posix_memalign(void **memptr, u
   return 0;
 }
 
-uptr asan_malloc_usable_size(void *ptr, StackTrace *stack) {
-  CHECK(stack);
+uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp) {
   if (ptr == 0) return 0;
   uptr usable_size = AllocationSize(reinterpret_cast<uptr>(ptr));
-  if (flags()->check_malloc_usable_size && (usable_size == 0))
-    ReportMallocUsableSizeNotOwned((uptr)ptr, stack);
+  if (flags()->check_malloc_usable_size && (usable_size == 0)) {
+    GET_STACK_TRACE_FATAL(pc, bp);
+    ReportMallocUsableSizeNotOwned((uptr)ptr, &stack);
+  }
   return usable_size;
 }
 

Modified: compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_linux.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_linux.cc Wed Nov 13 08:46:58 2013
@@ -105,8 +105,9 @@ INTERCEPTOR(void*, __libc_memalign, uptr
   ALIAS("memalign");
 
 INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
-  GET_STACK_TRACE_MALLOC;
-  return asan_malloc_usable_size(ptr, &stack);
+  GET_CURRENT_PC_BP_SP;
+  (void)sp;
+  return asan_malloc_usable_size(ptr, pc, bp);
 }
 
 // We avoid including malloc.h for portability reasons.

Modified: compiler-rt/trunk/lib/asan/asan_malloc_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_win.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_win.cc Wed Nov 13 08:46:58 2013
@@ -98,8 +98,9 @@ void* _recalloc(void* p, size_t n, size_
 
 SANITIZER_INTERFACE_ATTRIBUTE
 size_t _msize(void *ptr) {
-  GET_STACK_TRACE_MALLOC;
-  return asan_malloc_usable_size(ptr, &stack);
+  GET_CURRENT_PC_BP_SP;
+  (void)sp;
+  return asan_malloc_usable_size(ptr, pc, bp);
 }
 
 int _CrtDbgReport(int, const char*, int,

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Nov 13 08:46:58 2013
@@ -564,7 +564,7 @@ void ReportSIGSEGV(uptr pc, uptr sp, upt
   ReportErrorSummary("SEGV", &stack);
 }
 
-void ReportDoubleFree(uptr addr, StackTrace *stack) {
+void ReportDoubleFree(uptr addr, StackTrace *free_stack) {
   ScopedInErrorReport in_report;
   Decorator d;
   Printf("%s", d.Warning());
@@ -574,14 +574,15 @@ void ReportDoubleFree(uptr addr, StackTr
          "thread T%d%s:\n",
          addr, curr_tid,
          ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
-
   Printf("%s", d.EndWarning());
-  PrintStack(stack);
+  CHECK_GT(free_stack->size, 0);
+  GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
+  PrintStack(&stack);
   DescribeHeapAddress(addr, 1);
-  ReportErrorSummary("double-free", stack);
+  ReportErrorSummary("double-free", &stack);
 }
 
-void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
+void ReportFreeNotMalloced(uptr addr, StackTrace *free_stack) {
   ScopedInErrorReport in_report;
   Decorator d;
   Printf("%s", d.Warning());
@@ -591,12 +592,14 @@ void ReportFreeNotMalloced(uptr addr, St
              "which was not malloc()-ed: %p in thread T%d%s\n", addr,
          curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
   Printf("%s", d.EndWarning());
-  PrintStack(stack);
+  CHECK_GT(free_stack->size, 0);
+  GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
+  PrintStack(&stack);
   DescribeHeapAddress(addr, 1);
-  ReportErrorSummary("bad-free", stack);
+  ReportErrorSummary("bad-free", &stack);
 }
 
-void ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+void ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
                              AllocType alloc_type,
                              AllocType dealloc_type) {
   static const char *alloc_names[] =
@@ -610,9 +613,11 @@ void ReportAllocTypeMismatch(uptr addr,
   Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
         alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
   Printf("%s", d.EndWarning());
-  PrintStack(stack);
+  CHECK_GT(free_stack->size, 0);
+  GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
+  PrintStack(&stack);
   DescribeHeapAddress(addr, 1);
-  ReportErrorSummary("alloc-dealloc-mismatch", stack);
+  ReportErrorSummary("alloc-dealloc-mismatch", &stack);
   Report("HINT: if you don't care about these warnings you may set "
          "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
 }

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Wed Nov 13 08:46:58 2013
@@ -33,9 +33,9 @@ void DescribeThread(AsanThreadContext *c
 
 // Different kinds of error reports.
 void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);
-void NORETURN ReportDoubleFree(uptr addr, StackTrace *stack);
-void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *stack);
-void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
+void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
+void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
+void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack,
                                       AllocType alloc_type,
                                       AllocType dealloc_type);
 void NORETURN ReportMallocUsableSizeNotOwned(uptr addr,

Modified: compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc Wed Nov 13 08:46:58 2013
@@ -2,10 +2,16 @@
 // is set.
 
 // RUN: %clangxx_asan -g %s -o %t 2>&1
-// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 not %t 2>&1 | FileCheck %s
+
+// Find error and provide malloc context.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALLOC-STACK
 
 // No error here.
 // RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=0 %t
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
 #include <stdlib.h>
 
 static volatile char *x;
@@ -20,6 +26,6 @@ int main() {
 // CHECK: #{{.*}}main
 // CHECK: is located 0 bytes inside of 10-byte region
 // CHECK-NEXT: allocated by thread T0 here:
-// CHECK-NEXT: #0{{.*}}malloc
-// CHECK: #{{.*}}main
+// ALLOC-STACK-NEXT: #0{{.*}}malloc
+// ALLOC-STACK: #{{.*}}main
 // CHECK: HINT: {{.*}} you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0

Modified: compiler-rt/trunk/lib/asan/lit_tests/TestCases/double-free.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/double-free.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/double-free.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/double-free.cc Wed Nov 13 08:46:58 2013
@@ -1,4 +1,9 @@
-// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MALLOC-CTX
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
 
 #include <stdlib.h>
 #include <string.h>
@@ -11,8 +16,8 @@ int main(int argc, char **argv) {
   // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0
   // CHECK: double-free.cc:[[@LINE-2]]
   // CHECK: freed by thread T0 here:
-  // CHECK: double-free.cc:[[@LINE-5]]
+  // MALLOC-CTX: double-free.cc:[[@LINE-5]]
   // CHECK: allocated by thread T0 here:
-  // CHECK: double-free.cc:[[@LINE-10]]
+  // MALLOC-CTX: double-free.cc:[[@LINE-10]]
   return res;
 }

Modified: compiler-rt/trunk/lib/asan/lit_tests/TestCases/invalid-free.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/TestCases/invalid-free.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/TestCases/invalid-free.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/TestCases/invalid-free.cc Wed Nov 13 08:46:58 2013
@@ -1,4 +1,9 @@
-// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MALLOC-CTX
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
 
 #include <stdlib.h>
 #include <string.h>
@@ -11,6 +16,6 @@ int main(int argc, char **argv) {
   // CHECK: invalid-free.cc:[[@LINE-2]]
   // CHECK: is located 5 bytes inside of 10-byte region
   // CHECK: allocated by thread T0 here:
-  // CHECK: invalid-free.cc:[[@LINE-8]]
+  // MALLOC-CTX: invalid-free.cc:[[@LINE-8]]
   return res;
 }

Modified: compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_noinst_test.cc Wed Nov 13 08:46:58 2013
@@ -106,7 +106,7 @@ static void MallocStress(size_t n) {
       size_t alignment = 1 << (my_rand_r(&seed) % 10 + 1);
       char *ptr = (char*)__asan::asan_memalign(alignment, size,
                                                &stack2, __asan::FROM_MALLOC);
-      EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, &stack2));
+      EXPECT_EQ(size, __asan::asan_malloc_usable_size(ptr, 0, 0));
       vec.push_back(ptr);
       ptr[0] = 0;
       ptr[size-1] = 0;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace.h Wed Nov 13 08:46:58 2013
@@ -33,6 +33,7 @@ static const uptr kStackTraceMax = 256;
 struct StackTrace {
   typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
                                      int out_size);
+  uptr top_frame_bp;
   uptr size;
   uptr trace[kStackTraceMax];
 
@@ -41,6 +42,7 @@ struct StackTrace {
                          SymbolizeCallback symbolize_callback = 0);
 
   void CopyFrom(const uptr *src, uptr src_size) {
+    top_frame_bp = 0;
     size = src_size;
     if (size > kStackTraceMax) size = kStackTraceMax;
     for (uptr i = 0; i < size; i++)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc Wed Nov 13 08:46:58 2013
@@ -21,6 +21,8 @@ void StackTrace::Unwind(uptr max_depth,
     SlowUnwindStack(pc, max_depth);
   else
     FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
+
+  top_frame_bp = size ? bp : 0;
 }
 
 }  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc?rev=194579&r1=194578&r2=194579&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc Wed Nov 13 08:46:58 2013
@@ -99,6 +99,7 @@ TEST_F(FastUnwindTest, OneFrameStackTrac
     return;
   EXPECT_EQ(1U, trace.size);
   EXPECT_EQ(start_pc, trace.trace[0]);
+  EXPECT_EQ((uptr)&fake_stack[0], trace.top_frame_bp);
 }
 
 }  // namespace __sanitizer





More information about the llvm-commits mailing list