asan_report.cc revision e218beb2d14b663bd277158f386a86d0e62fef74
1//===-- asan_report.cc ----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// This file contains error reporting code.
13//===----------------------------------------------------------------------===//
14#include "asan_internal.h"
15#include "asan_mapping.h"
16#include "asan_report.h"
17#include "asan_stack.h"
18#include "asan_thread_registry.h"
19
20namespace __asan {
21
22// ---------------------- Address Descriptions ------------------- {{{1
23
24bool DescribeAddressIfShadow(uptr addr) {
25  if (AddrIsInMem(addr))
26    return false;
27  static const char kAddrInShadowReport[] =
28      "Address %p is located in the %s.\n";
29  if (AddrIsInShadowGap(addr)) {
30    AsanPrintf(kAddrInShadowReport, addr, "shadow gap area");
31    return true;
32  }
33  if (AddrIsInHighShadow(addr)) {
34    AsanPrintf(kAddrInShadowReport, addr, "high shadow area");
35    return true;
36  }
37  if (AddrIsInLowShadow(addr)) {
38    AsanPrintf(kAddrInShadowReport, addr, "low shadow area");
39    return true;
40  }
41  CHECK(0 && "Address is not in memory and not in shadow?");
42  return false;
43}
44
45bool DescribeAddressIfStack(uptr addr, uptr access_size) {
46  AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
47  if (!t) return false;
48  const sptr kBufSize = 4095;
49  char buf[kBufSize];
50  uptr offset = 0;
51  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
52  // This string is created by the compiler and has the following form:
53  // "FunctioName n alloc_1 alloc_2 ... alloc_n"
54  // where alloc_i looks like "offset size len ObjectName ".
55  CHECK(frame_descr);
56  // Report the function name and the offset.
57  const char *name_end = internal_strchr(frame_descr, ' ');
58  CHECK(name_end);
59  buf[0] = 0;
60  internal_strncat(buf, frame_descr,
61                   Min(kBufSize,
62                       static_cast<sptr>(name_end - frame_descr)));
63  AsanPrintf("Address %p is located at offset %zu "
64             "in frame <%s> of T%d's stack:\n",
65             (void*)addr, offset, buf, t->tid());
66  // Report the number of stack objects.
67  char *p;
68  uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
69  CHECK(n_objects > 0);
70  AsanPrintf("  This frame has %zu object(s):\n", n_objects);
71  // Report all objects in this frame.
72  for (uptr i = 0; i < n_objects; i++) {
73    uptr beg, size;
74    sptr len;
75    beg  = internal_simple_strtoll(p, &p, 10);
76    size = internal_simple_strtoll(p, &p, 10);
77    len  = internal_simple_strtoll(p, &p, 10);
78    if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
79      AsanPrintf("AddressSanitizer can't parse the stack frame "
80                 "descriptor: |%s|\n", frame_descr);
81      break;
82    }
83    p++;
84    buf[0] = 0;
85    internal_strncat(buf, p, Min(kBufSize, len));
86    p += len;
87    AsanPrintf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
88  }
89  AsanPrintf("HINT: this may be a false positive if your program uses "
90             "some custom stack unwind mechanism\n"
91             "      (longjmp and C++ exceptions *are* supported)\n");
92  t->summary()->Announce();
93  return true;
94}
95
96void DescribeAddress(uptr addr, uptr access_size) {
97  // Check if this is shadow or shadow gap.
98  if (DescribeAddressIfShadow(addr))
99    return;
100  CHECK(AddrIsInMem(addr));
101  if (DescribeAddressIfGlobal(addr))
102    return;
103  if (DescribeAddressIfStack(addr, access_size))
104    return;
105  // Assume it is a heap address.
106  DescribeHeapAddress(addr, access_size);
107}
108
109// -------------------- Different kinds of reports ----------------- {{{1
110
111void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
112  AsanReport("ERROR: AddressSanitizer crashed on unknown address %p"
113             " (pc %p sp %p bp %p T%d)\n",
114             (void*)addr, (void*)pc, (void*)sp, (void*)bp,
115             asanThreadRegistry().GetCurrentTidOrInvalid());
116  AsanPrintf("AddressSanitizer can not provide additional info. ABORTING\n");
117  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
118  stack.PrintStack();
119  ShowStatsAndAbort();
120}
121
122void ReportDoubleFree(uptr addr, AsanStackTrace *stack) {
123  AsanReport("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
124  stack->PrintStack();
125  DescribeHeapAddress(addr, 1);
126  ShowStatsAndAbort();
127}
128
129void ReportFreeNotMalloced(uptr addr, AsanStackTrace *stack) {
130  AsanReport("ERROR: AddressSanitizer attempting free on address "
131             "which was not malloc()-ed: %p\n", addr);
132  stack->PrintStack();
133  ShowStatsAndAbort();
134}
135
136void ReportMallocUsableSizeNotOwned(uptr addr, AsanStackTrace *stack) {
137  AsanReport("ERROR: AddressSanitizer attempting to call "
138             "malloc_usable_size() for pointer which is "
139             "not owned: %p\n", addr);
140  stack->PrintStack();
141  DescribeHeapAddress(addr, 1);
142  ShowStatsAndAbort();
143}
144
145void ReportAsanGetAllocatedSizeNotOwned(uptr addr, AsanStackTrace *stack) {
146  AsanReport("ERROR: AddressSanitizer attempting to call "
147             "__asan_get_allocated_size() for pointer which is "
148             "not owned: %p\n", addr);
149  stack->PrintStack();
150  DescribeHeapAddress(addr, 1);
151  ShowStatsAndAbort();
152}
153
154void ReportStringFunctionMemoryRangesOverlap(
155    const char *function, const char *offset1, uptr length1,
156    const char *offset2, uptr length2, AsanStackTrace *stack) {
157  AsanReport("ERROR: AddressSanitizer %s-param-overlap: "
158             "memory ranges [%p,%p) and [%p, %p) overlap\n", \
159             function, offset1, offset1 + length1, offset2, offset2 + length2);
160  stack->PrintStack();
161  ShowStatsAndAbort();
162}
163
164}  // namespace __asan
165