blob: 2fbf8fd8ac8696e8ea657b705972193b759a6b6f [file] [log] [blame]
Alexey Samsonov73545092012-08-09 07:40:58 +00001//===-- 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//===----------------------------------------------------------------------===//
Alexey Samsonov98737922012-08-10 15:13:05 +000014#include "asan_flags.h"
Alexey Samsonov73545092012-08-09 07:40:58 +000015#include "asan_internal.h"
Alexey Samsonove218beb2012-08-09 09:06:52 +000016#include "asan_mapping.h"
Alexey Samsonov73545092012-08-09 07:40:58 +000017#include "asan_report.h"
18#include "asan_stack.h"
Alexey Samsonove4bfca22012-08-09 09:27:24 +000019#include "asan_thread.h"
Alexey Samsonov73545092012-08-09 07:40:58 +000020#include "asan_thread_registry.h"
21
22namespace __asan {
23
Alexey Samsonovf657a192012-08-13 11:23:40 +000024// -------------------- User-specified callbacks ----------------- {{{1
Alexey Samsonovc98570b2012-08-09 10:56:57 +000025static void (*error_report_callback)(const char*);
26static char *error_message_buffer = 0;
27static uptr error_message_buffer_pos = 0;
28static uptr error_message_buffer_size = 0;
29
30void AppendToErrorMessageBuffer(const char *buffer) {
31 if (error_message_buffer) {
32 uptr length = internal_strlen(buffer);
33 CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
34 uptr remaining = error_message_buffer_size - error_message_buffer_pos;
35 internal_strncpy(error_message_buffer + error_message_buffer_pos,
36 buffer, remaining);
37 error_message_buffer[error_message_buffer_size - 1] = '\0';
38 // FIXME: reallocate the buffer instead of truncating the message.
39 error_message_buffer_pos += remaining > length ? length : remaining;
40 }
41}
42
Alexey Samsonov98737922012-08-10 15:13:05 +000043// ---------------------- Helper functions ----------------------- {{{1
44
45static void PrintBytes(const char *before, uptr *a) {
46 u8 *bytes = (u8*)a;
47 uptr byte_num = (__WORDSIZE) / 8;
Kostya Serebryany283c2962012-08-28 11:34:40 +000048 Printf("%s%p:", before, (void*)a);
Alexey Samsonov98737922012-08-10 15:13:05 +000049 for (uptr i = 0; i < byte_num; i++) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000050 Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
Alexey Samsonov98737922012-08-10 15:13:05 +000051 }
Kostya Serebryany283c2962012-08-28 11:34:40 +000052 Printf("\n");
Alexey Samsonov98737922012-08-10 15:13:05 +000053}
54
55static void PrintShadowMemoryForAddress(uptr addr) {
56 if (!AddrIsInMem(addr))
57 return;
58 uptr shadow_addr = MemToShadow(addr);
Kostya Serebryany283c2962012-08-28 11:34:40 +000059 Printf("Shadow byte and word:\n");
60 Printf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
Alexey Samsonov98737922012-08-10 15:13:05 +000061 uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
62 PrintBytes(" ", (uptr*)(aligned_shadow));
Kostya Serebryany283c2962012-08-28 11:34:40 +000063 Printf("More shadow bytes:\n");
Alexey Samsonov98737922012-08-10 15:13:05 +000064 for (int i = -4; i <= 4; i++) {
65 const char *prefix = (i == 0) ? "=>" : " ";
66 PrintBytes(prefix, (uptr*)(aligned_shadow + i * kWordSize));
67 }
68}
69
70static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
71 const char *zone_name) {
72 if (zone_ptr) {
73 if (zone_name) {
Kostya Serebryany283c2962012-08-28 11:34:40 +000074 Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
Alexey Samsonov98737922012-08-10 15:13:05 +000075 ptr, zone_ptr, zone_name);
76 } else {
Kostya Serebryany283c2962012-08-28 11:34:40 +000077 Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
Alexey Samsonov98737922012-08-10 15:13:05 +000078 ptr, zone_ptr);
79 }
80 } else {
Kostya Serebryany283c2962012-08-28 11:34:40 +000081 Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
Alexey Samsonov98737922012-08-10 15:13:05 +000082 }
83}
84
Alexey Samsonove218beb2012-08-09 09:06:52 +000085// ---------------------- Address Descriptions ------------------- {{{1
86
Alexey Samsonove4bfca22012-08-09 09:27:24 +000087static bool IsASCII(unsigned char c) {
Alexey Samsonov98737922012-08-10 15:13:05 +000088 return /*0x00 <= c &&*/ c <= 0x7F;
Alexey Samsonove4bfca22012-08-09 09:27:24 +000089}
90
91// Check if the global is a zero-terminated ASCII string. If so, print it.
92static void PrintGlobalNameIfASCII(const __asan_global &g) {
93 for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
94 if (!IsASCII(*(unsigned char*)p)) return;
95 }
96 if (*(char*)(g.beg + g.size - 1) != 0) return;
Kostya Serebryany283c2962012-08-28 11:34:40 +000097 Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
Alexey Samsonove4bfca22012-08-09 09:27:24 +000098}
99
100bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) {
101 if (addr < g.beg - kGlobalAndStackRedzone) return false;
102 if (addr >= g.beg + g.size_with_redzone) return false;
Kostya Serebryany283c2962012-08-28 11:34:40 +0000103 Printf("%p is located ", (void*)addr);
Alexey Samsonove4bfca22012-08-09 09:27:24 +0000104 if (addr < g.beg) {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000105 Printf("%zd bytes to the left", g.beg - addr);
Alexey Samsonove4bfca22012-08-09 09:27:24 +0000106 } else if (addr >= g.beg + g.size) {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000107 Printf("%zd bytes to the right", addr - (g.beg + g.size));
Alexey Samsonove4bfca22012-08-09 09:27:24 +0000108 } else {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000109 Printf("%zd bytes inside", addr - g.beg); // Can it happen?
Alexey Samsonove4bfca22012-08-09 09:27:24 +0000110 }
Kostya Serebryany283c2962012-08-28 11:34:40 +0000111 Printf(" of global variable '%s' (0x%zx) of size %zu\n",
Alexey Samsonove4bfca22012-08-09 09:27:24 +0000112 g.name, g.beg, g.size);
113 PrintGlobalNameIfASCII(g);
114 return true;
115}
116
Alexey Samsonove218beb2012-08-09 09:06:52 +0000117bool DescribeAddressIfShadow(uptr addr) {
118 if (AddrIsInMem(addr))
119 return false;
120 static const char kAddrInShadowReport[] =
121 "Address %p is located in the %s.\n";
122 if (AddrIsInShadowGap(addr)) {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000123 Printf(kAddrInShadowReport, addr, "shadow gap area");
Alexey Samsonove218beb2012-08-09 09:06:52 +0000124 return true;
125 }
126 if (AddrIsInHighShadow(addr)) {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000127 Printf(kAddrInShadowReport, addr, "high shadow area");
Alexey Samsonove218beb2012-08-09 09:06:52 +0000128 return true;
129 }
130 if (AddrIsInLowShadow(addr)) {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000131 Printf(kAddrInShadowReport, addr, "low shadow area");
Alexey Samsonove218beb2012-08-09 09:06:52 +0000132 return true;
133 }
134 CHECK(0 && "Address is not in memory and not in shadow?");
135 return false;
136}
137
138bool DescribeAddressIfStack(uptr addr, uptr access_size) {
139 AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
140 if (!t) return false;
141 const sptr kBufSize = 4095;
142 char buf[kBufSize];
143 uptr offset = 0;
144 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
145 // This string is created by the compiler and has the following form:
146 // "FunctioName n alloc_1 alloc_2 ... alloc_n"
147 // where alloc_i looks like "offset size len ObjectName ".
148 CHECK(frame_descr);
149 // Report the function name and the offset.
150 const char *name_end = internal_strchr(frame_descr, ' ');
151 CHECK(name_end);
152 buf[0] = 0;
153 internal_strncat(buf, frame_descr,
154 Min(kBufSize,
155 static_cast<sptr>(name_end - frame_descr)));
Kostya Serebryany283c2962012-08-28 11:34:40 +0000156 Printf("Address %p is located at offset %zu "
Alexey Samsonove218beb2012-08-09 09:06:52 +0000157 "in frame <%s> of T%d's stack:\n",
158 (void*)addr, offset, buf, t->tid());
159 // Report the number of stack objects.
160 char *p;
161 uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
162 CHECK(n_objects > 0);
Kostya Serebryany283c2962012-08-28 11:34:40 +0000163 Printf(" This frame has %zu object(s):\n", n_objects);
Alexey Samsonove218beb2012-08-09 09:06:52 +0000164 // Report all objects in this frame.
165 for (uptr i = 0; i < n_objects; i++) {
166 uptr beg, size;
167 sptr len;
168 beg = internal_simple_strtoll(p, &p, 10);
169 size = internal_simple_strtoll(p, &p, 10);
170 len = internal_simple_strtoll(p, &p, 10);
171 if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
Kostya Serebryany283c2962012-08-28 11:34:40 +0000172 Printf("AddressSanitizer can't parse the stack frame "
Alexey Samsonove218beb2012-08-09 09:06:52 +0000173 "descriptor: |%s|\n", frame_descr);
174 break;
175 }
176 p++;
177 buf[0] = 0;
178 internal_strncat(buf, p, Min(kBufSize, len));
179 p += len;
Kostya Serebryany283c2962012-08-28 11:34:40 +0000180 Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
Alexey Samsonove218beb2012-08-09 09:06:52 +0000181 }
Kostya Serebryany283c2962012-08-28 11:34:40 +0000182 Printf("HINT: this may be a false positive if your program uses "
Alexey Samsonove218beb2012-08-09 09:06:52 +0000183 "some custom stack unwind mechanism\n"
184 " (longjmp and C++ exceptions *are* supported)\n");
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000185 DescribeThread(t->summary());
Alexey Samsonove218beb2012-08-09 09:06:52 +0000186 return true;
187}
188
Alexey Samsonov5c153fa2012-09-18 07:38:10 +0000189static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
190 uptr access_size) {
191 uptr offset;
192 Printf("%p is located ", (void*)addr);
193 if (chunk.AddrIsInside(addr, access_size, &offset)) {
194 Printf("%zu bytes inside of", offset);
195 } else if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
196 Printf("%zu bytes to the left of", offset);
197 } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
198 Printf("%zu bytes to the right of", offset);
199 } else {
200 Printf(" somewhere around (this is AddressSanitizer bug!)");
201 }
202 Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
203 (void*)(chunk.Beg()), (void*)(chunk.End()));
204}
205
206void DescribeHeapAddress(uptr addr, uptr access_size) {
207 AsanChunkView chunk = FindHeapChunkByAddress(addr);
208 if (!chunk.IsValid()) return;
209 DescribeAccessToHeapChunk(chunk, addr, access_size);
210 CHECK(chunk.AllocTid() != kInvalidTid);
211 AsanThreadSummary *alloc_thread =
212 asanThreadRegistry().FindByTid(chunk.AllocTid());
213 StackTrace alloc_stack;
214 chunk.GetAllocStack(&alloc_stack);
215 AsanThread *t = asanThreadRegistry().GetCurrent();
216 CHECK(t);
217 if (chunk.FreeTid() != kInvalidTid) {
218 AsanThreadSummary *free_thread =
219 asanThreadRegistry().FindByTid(chunk.FreeTid());
220 Printf("freed by thread T%d here:\n", free_thread->tid());
221 StackTrace free_stack;
222 chunk.GetFreeStack(&free_stack);
223 PrintStack(&free_stack);
224 Printf("previously allocated by thread T%d here:\n", alloc_thread->tid());
225 PrintStack(&alloc_stack);
226 DescribeThread(t->summary());
227 DescribeThread(free_thread);
228 DescribeThread(alloc_thread);
229 } else {
230 Printf("allocated by thread T%d here:\n", alloc_thread->tid());
231 PrintStack(&alloc_stack);
232 DescribeThread(t->summary());
233 DescribeThread(alloc_thread);
234 }
235}
236
Alexey Samsonove218beb2012-08-09 09:06:52 +0000237void DescribeAddress(uptr addr, uptr access_size) {
238 // Check if this is shadow or shadow gap.
239 if (DescribeAddressIfShadow(addr))
240 return;
241 CHECK(AddrIsInMem(addr));
242 if (DescribeAddressIfGlobal(addr))
243 return;
244 if (DescribeAddressIfStack(addr, access_size))
245 return;
246 // Assume it is a heap address.
247 DescribeHeapAddress(addr, access_size);
248}
249
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000250// ------------------- Thread description -------------------- {{{1
251
252void DescribeThread(AsanThreadSummary *summary) {
253 CHECK(summary);
254 // No need to announce the main thread.
255 if (summary->tid() == 0 || summary->announced()) {
256 return;
257 }
258 summary->set_announced(true);
259 Printf("Thread T%d created by T%d here:\n",
260 summary->tid(), summary->parent_tid());
261 PrintStack(summary->stack());
262 // Recursively described parent thread if needed.
263 if (flags()->print_full_thread_history) {
264 AsanThreadSummary *parent_summary =
265 asanThreadRegistry().FindByTid(summary->parent_tid());
266 DescribeThread(parent_summary);
267 }
268}
269
Alexey Samsonove218beb2012-08-09 09:06:52 +0000270// -------------------- Different kinds of reports ----------------- {{{1
271
Alexey Samsonov98737922012-08-10 15:13:05 +0000272// Use ScopedInErrorReport to run common actions just before and
273// immediately after printing error report.
274class ScopedInErrorReport {
275 public:
276 ScopedInErrorReport() {
277 static atomic_uint32_t num_calls;
Alexey Samsonov62e27092012-09-17 08:02:19 +0000278 static u32 reporting_thread_tid;
Alexey Samsonov98737922012-08-10 15:13:05 +0000279 if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
280 // Do not print more than one report, otherwise they will mix up.
281 // Error reporting functions shouldn't return at this situation, as
282 // they are defined as no-return.
Kostya Serebryany283c2962012-08-28 11:34:40 +0000283 Report("AddressSanitizer: while reporting a bug found another one."
Alexey Samsonov98737922012-08-10 15:13:05 +0000284 "Ignoring.\n");
Alexey Samsonov62e27092012-09-17 08:02:19 +0000285 u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
286 if (current_tid != reporting_thread_tid) {
287 // ASan found two bugs in different threads simultaneously. Sleep
288 // long enough to make sure that the thread which started to print
289 // an error report will finish doing it.
290 SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
291 }
Alexey Samsonovbe98caf2012-08-13 09:57:19 +0000292 Die();
Alexey Samsonov98737922012-08-10 15:13:05 +0000293 }
Alexey Samsonov86633432012-10-02 14:06:39 +0000294 __asan_on_error();
Alexey Samsonov62e27092012-09-17 08:02:19 +0000295 reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
Kostya Serebryany283c2962012-08-28 11:34:40 +0000296 Printf("===================================================="
Alexey Samsonov62e27092012-09-17 08:02:19 +0000297 "=============\n");
298 if (reporting_thread_tid != kInvalidTid) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000299 // We started reporting an error message. Stop using the fake stack
300 // in case we call an instrumented function from a symbolizer.
Alexey Samsonov62e27092012-09-17 08:02:19 +0000301 AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
302 CHECK(curr_thread);
Alexey Samsonov98737922012-08-10 15:13:05 +0000303 curr_thread->fake_stack().StopUsingFakeStack();
304 }
305 }
306 // Destructor is NORETURN, as functions that report errors are.
307 NORETURN ~ScopedInErrorReport() {
308 // Make sure the current thread is announced.
309 AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
310 if (curr_thread) {
Alexey Samsonov71b42c92012-09-05 07:37:15 +0000311 DescribeThread(curr_thread->summary());
Alexey Samsonov98737922012-08-10 15:13:05 +0000312 }
313 // Print memory stats.
314 __asan_print_accumulated_stats();
315 if (error_report_callback) {
316 error_report_callback(error_message_buffer);
317 }
Kostya Serebryany283c2962012-08-28 11:34:40 +0000318 Report("ABORTING\n");
Alexey Samsonov98737922012-08-10 15:13:05 +0000319 Die();
320 }
321};
322
Alexey Samsonov73545092012-08-09 07:40:58 +0000323void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000324 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000325 Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
Alexey Samsonov73545092012-08-09 07:40:58 +0000326 " (pc %p sp %p bp %p T%d)\n",
327 (void*)addr, (void*)pc, (void*)sp, (void*)bp,
328 asanThreadRegistry().GetCurrentTidOrInvalid());
Kostya Serebryany283c2962012-08-28 11:34:40 +0000329 Printf("AddressSanitizer can not provide additional info.\n");
Alexey Samsonov73545092012-08-09 07:40:58 +0000330 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000331 PrintStack(&stack);
Alexey Samsonov73545092012-08-09 07:40:58 +0000332}
333
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000334void ReportDoubleFree(uptr addr, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000335 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000336 Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000337 PrintStack(stack);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000338 DescribeHeapAddress(addr, 1);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000339}
340
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000341void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000342 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000343 Report("ERROR: AddressSanitizer: attempting free on address "
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000344 "which was not malloc()-ed: %p\n", addr);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000345 PrintStack(stack);
Alexey Samsonov98737922012-08-10 15:13:05 +0000346 DescribeHeapAddress(addr, 1);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000347}
348
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000349void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000350 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000351 Report("ERROR: AddressSanitizer: attempting to call "
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000352 "malloc_usable_size() for pointer which is "
353 "not owned: %p\n", addr);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000354 PrintStack(stack);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000355 DescribeHeapAddress(addr, 1);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000356}
357
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000358void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000359 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000360 Report("ERROR: AddressSanitizer: attempting to call "
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000361 "__asan_get_allocated_size() for pointer which is "
362 "not owned: %p\n", addr);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000363 PrintStack(stack);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000364 DescribeHeapAddress(addr, 1);
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000365}
366
Alexey Samsonov487fee72012-08-09 08:32:33 +0000367void ReportStringFunctionMemoryRangesOverlap(
368 const char *function, const char *offset1, uptr length1,
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000369 const char *offset2, uptr length2, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000370 ScopedInErrorReport in_report;
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000371 Report("ERROR: AddressSanitizer: %s-param-overlap: "
Alexey Samsonov487fee72012-08-09 08:32:33 +0000372 "memory ranges [%p,%p) and [%p, %p) overlap\n", \
373 function, offset1, offset1 + length1, offset2, offset2 + length2);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000374 PrintStack(stack);
Alexey Samsonov98737922012-08-10 15:13:05 +0000375 DescribeAddress((uptr)offset1, length1);
376 DescribeAddress((uptr)offset2, length2);
Alexey Samsonov487fee72012-08-09 08:32:33 +0000377}
Alexey Samsonovf7c1d182012-08-09 08:15:46 +0000378
Alexey Samsonov663c5012012-08-09 12:15:40 +0000379// ----------------------- Mac-specific reports ----------------- {{{1
380
Alexey Samsonov663c5012012-08-09 12:15:40 +0000381void WarnMacFreeUnallocated(
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000382 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000383 // Just print a warning here.
Kostya Serebryany283c2962012-08-28 11:34:40 +0000384 Printf("free_common(%p) -- attempting to free unallocated memory.\n"
Alexey Samsonov663c5012012-08-09 12:15:40 +0000385 "AddressSanitizer is ignoring this error on Mac OS now.\n",
386 addr);
387 PrintZoneForPointer(addr, zone_ptr, zone_name);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000388 PrintStack(stack);
Alexey Samsonov98737922012-08-10 15:13:05 +0000389 DescribeHeapAddress(addr, 1);
Alexey Samsonov663c5012012-08-09 12:15:40 +0000390}
391
392void ReportMacMzReallocUnknown(
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000393 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000394 ScopedInErrorReport in_report;
Kostya Serebryany283c2962012-08-28 11:34:40 +0000395 Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
Alexey Samsonov663c5012012-08-09 12:15:40 +0000396 "This is an unrecoverable problem, exiting now.\n",
397 addr);
398 PrintZoneForPointer(addr, zone_ptr, zone_name);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000399 PrintStack(stack);
Alexey Samsonov98737922012-08-10 15:13:05 +0000400 DescribeHeapAddress(addr, 1);
Alexey Samsonov663c5012012-08-09 12:15:40 +0000401}
402
403void ReportMacCfReallocUnknown(
Kostya Serebryanyc3390df2012-08-28 11:54:30 +0000404 uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000405 ScopedInErrorReport in_report;
Kostya Serebryany283c2962012-08-28 11:34:40 +0000406 Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
Alexey Samsonov663c5012012-08-09 12:15:40 +0000407 "This is an unrecoverable problem, exiting now.\n",
408 addr);
409 PrintZoneForPointer(addr, zone_ptr, zone_name);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000410 PrintStack(stack);
Alexey Samsonov98737922012-08-10 15:13:05 +0000411 DescribeHeapAddress(addr, 1);
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000412}
413
Alexey Samsonov812ff902012-08-09 11:29:13 +0000414} // namespace __asan
415
416// --------------------------- Interface --------------------- {{{1
417using namespace __asan; // NOLINT
418
419void __asan_report_error(uptr pc, uptr bp, uptr sp,
420 uptr addr, bool is_write, uptr access_size) {
Alexey Samsonov98737922012-08-10 15:13:05 +0000421 ScopedInErrorReport in_report;
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000422
Alexey Samsonov98737922012-08-10 15:13:05 +0000423 // Determine the error type.
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000424 const char *bug_descr = "unknown-crash";
425 if (AddrIsInMem(addr)) {
426 u8 *shadow_addr = (u8*)MemToShadow(addr);
427 // If we are accessing 16 bytes, look at the second shadow byte.
428 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
429 shadow_addr++;
430 // If we are in the partial right redzone, look at the next shadow byte.
431 if (*shadow_addr > 0 && *shadow_addr < 128)
432 shadow_addr++;
433 switch (*shadow_addr) {
434 case kAsanHeapLeftRedzoneMagic:
435 case kAsanHeapRightRedzoneMagic:
436 bug_descr = "heap-buffer-overflow";
437 break;
438 case kAsanHeapFreeMagic:
439 bug_descr = "heap-use-after-free";
440 break;
441 case kAsanStackLeftRedzoneMagic:
442 bug_descr = "stack-buffer-underflow";
443 break;
Kostya Serebryany3945c582012-08-21 14:10:25 +0000444 case kAsanInitializationOrderMagic:
445 bug_descr = "initialization-order-fiasco";
446 break;
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000447 case kAsanStackMidRedzoneMagic:
448 case kAsanStackRightRedzoneMagic:
449 case kAsanStackPartialRedzoneMagic:
450 bug_descr = "stack-buffer-overflow";
451 break;
452 case kAsanStackAfterReturnMagic:
453 bug_descr = "stack-use-after-return";
454 break;
455 case kAsanUserPoisonedMemoryMagic:
456 bug_descr = "use-after-poison";
457 break;
458 case kAsanGlobalRedzoneMagic:
459 bug_descr = "global-buffer-overflow";
460 break;
461 }
462 }
463
Kostya Serebryany69d8ede2012-10-15 13:04:58 +0000464 Report("ERROR: AddressSanitizer: %s on address "
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000465 "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
466 bug_descr, (void*)addr, pc, bp, sp);
467
Alexey Samsonov98737922012-08-10 15:13:05 +0000468 u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
Kostya Serebryany283c2962012-08-28 11:34:40 +0000469 Printf("%s of size %zu at %p thread T%d\n",
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000470 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
471 access_size, (void*)addr, curr_tid);
472
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000473 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
Kostya Serebryanycc347222012-08-28 13:49:49 +0000474 PrintStack(&stack);
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000475
476 DescribeAddress(addr, access_size);
477
Alexey Samsonov98737922012-08-10 15:13:05 +0000478 PrintShadowMemoryForAddress(addr);
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000479}
480
Alexey Samsonovc98570b2012-08-09 10:56:57 +0000481void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
482 error_report_callback = callback;
483 if (callback) {
484 error_message_buffer_size = 1 << 16;
485 error_message_buffer =
486 (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
487 error_message_buffer_pos = 0;
488 }
489}
Alexey Samsonovf657a192012-08-13 11:23:40 +0000490
Alexey Samsonov86633432012-10-02 14:06:39 +0000491// Provide default implementation of __asan_on_error that does nothing
492// and may be overriden by user.
493SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
494void __asan_on_error() {}