1 //===-- asan_report.cc ----------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
10 // This file contains error reporting code.
11 //===----------------------------------------------------------------------===//
12 #include "asan_flags.h"
13 #include "asan_internal.h"
14 #include "asan_mapping.h"
15 #include "asan_report.h"
16 #include "asan_stack.h"
17 #include "asan_thread.h"
18 #include "asan_thread_registry.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 #include "sanitizer_common/sanitizer_report_decorator.h"
21 #include "sanitizer_common/sanitizer_symbolizer.h"
22 
23 namespace __asan {
24 
25 // -------------------- User-specified callbacks ----------------- {{{1
26 static void (*error_report_callback)(const char*);
27 static char *error_message_buffer = 0;
28 static uptr error_message_buffer_pos = 0;
29 static uptr error_message_buffer_size = 0;
30 
AppendToErrorMessageBuffer(const char * buffer)31 void AppendToErrorMessageBuffer(const char *buffer) {
32   if (error_message_buffer) {
33     uptr length = internal_strlen(buffer);
34     CHECK_GE(error_message_buffer_size, error_message_buffer_pos);
35     uptr remaining = error_message_buffer_size - error_message_buffer_pos;
36     internal_strncpy(error_message_buffer + error_message_buffer_pos,
37                      buffer, remaining);
38     error_message_buffer[error_message_buffer_size - 1] = '\0';
39     // FIXME: reallocate the buffer instead of truncating the message.
40     error_message_buffer_pos += remaining > length ? length : remaining;
41   }
42 }
43 
44 // ---------------------- Decorator ------------------------------ {{{1
PrintsToTtyCached()45 bool PrintsToTtyCached() {
46   static int cached = 0;
47   static bool prints_to_tty;
48   if (!cached) {  // Ok wrt threads since we are printing only from one thread.
49     prints_to_tty = PrintsToTty();
50     cached = 1;
51   }
52   return prints_to_tty;
53 }
54 class Decorator: private __sanitizer::AnsiColorDecorator {
55  public:
Decorator()56   Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
Warning()57   const char *Warning()    { return Red(); }
EndWarning()58   const char *EndWarning() { return Default(); }
Access()59   const char *Access()     { return Blue(); }
EndAccess()60   const char *EndAccess()  { return Default(); }
Location()61   const char *Location()   { return Green(); }
EndLocation()62   const char *EndLocation() { return Default(); }
Allocation()63   const char *Allocation()  { return Magenta(); }
EndAllocation()64   const char *EndAllocation()  { return Default(); }
65 
ShadowByte(u8 byte)66   const char *ShadowByte(u8 byte) {
67     switch (byte) {
68       case kAsanHeapLeftRedzoneMagic:
69       case kAsanHeapRightRedzoneMagic:
70         return Red();
71       case kAsanHeapFreeMagic:
72         return Magenta();
73       case kAsanStackLeftRedzoneMagic:
74       case kAsanStackMidRedzoneMagic:
75       case kAsanStackRightRedzoneMagic:
76       case kAsanStackPartialRedzoneMagic:
77         return Red();
78       case kAsanStackAfterReturnMagic:
79         return Magenta();
80       case kAsanInitializationOrderMagic:
81         return Cyan();
82       case kAsanUserPoisonedMemoryMagic:
83         return Blue();
84       case kAsanStackUseAfterScopeMagic:
85         return Magenta();
86       case kAsanGlobalRedzoneMagic:
87         return Red();
88       case kAsanInternalHeapMagic:
89         return Yellow();
90       default:
91         return Default();
92     }
93   }
EndShadowByte()94   const char *EndShadowByte() { return Default(); }
95 };
96 
97 // ---------------------- Helper functions ----------------------- {{{1
98 
PrintShadowByte(const char * before,u8 byte,const char * after="\\n")99 static void PrintShadowByte(const char *before, u8 byte,
100                             const char *after = "\n") {
101   Decorator d;
102   Printf("%s%s%x%x%s%s", before,
103          d.ShadowByte(byte), byte >> 4, byte & 15, d.EndShadowByte(), after);
104 }
105 
PrintShadowBytes(const char * before,u8 * bytes,u8 * guilty,uptr n)106 static void PrintShadowBytes(const char *before, u8 *bytes,
107                              u8 *guilty, uptr n) {
108   Decorator d;
109   if (before)
110     Printf("%s%p:", before, bytes);
111   for (uptr i = 0; i < n; i++) {
112     u8 *p = bytes + i;
113     const char *before = p == guilty ? "[" :
114         p - 1 == guilty ? "" : " ";
115     const char *after = p == guilty ? "]" : "";
116     PrintShadowByte(before, *p, after);
117   }
118   Printf("\n");
119 }
120 
PrintLegend()121 static void PrintLegend() {
122   Printf("Shadow byte legend (one shadow byte represents %d "
123          "application bytes):\n", (int)SHADOW_GRANULARITY);
124   PrintShadowByte("  Addressable:           ", 0);
125   Printf("  Partially addressable: ");
126   for (uptr i = 1; i < SHADOW_GRANULARITY; i++)
127     PrintShadowByte("", i, " ");
128   Printf("\n");
129   PrintShadowByte("  Heap left redzone:     ", kAsanHeapLeftRedzoneMagic);
130   PrintShadowByte("  Heap righ redzone:     ", kAsanHeapRightRedzoneMagic);
131   PrintShadowByte("  Freed Heap region:     ", kAsanHeapFreeMagic);
132   PrintShadowByte("  Stack left redzone:    ", kAsanStackLeftRedzoneMagic);
133   PrintShadowByte("  Stack mid redzone:     ", kAsanStackMidRedzoneMagic);
134   PrintShadowByte("  Stack right redzone:   ", kAsanStackRightRedzoneMagic);
135   PrintShadowByte("  Stack partial redzone: ", kAsanStackPartialRedzoneMagic);
136   PrintShadowByte("  Stack after return:    ", kAsanStackAfterReturnMagic);
137   PrintShadowByte("  Stack use after scope: ", kAsanStackUseAfterScopeMagic);
138   PrintShadowByte("  Global redzone:        ", kAsanGlobalRedzoneMagic);
139   PrintShadowByte("  Global init order:     ", kAsanInitializationOrderMagic);
140   PrintShadowByte("  Poisoned by user:      ", kAsanUserPoisonedMemoryMagic);
141   PrintShadowByte("  ASan internal:         ", kAsanInternalHeapMagic);
142 }
143 
PrintShadowMemoryForAddress(uptr addr)144 static void PrintShadowMemoryForAddress(uptr addr) {
145   if (!AddrIsInMem(addr))
146     return;
147   uptr shadow_addr = MemToShadow(addr);
148   const uptr n_bytes_per_row = 16;
149   uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
150   Printf("Shadow bytes around the buggy address:\n");
151   for (int i = -5; i <= 5; i++) {
152     const char *prefix = (i == 0) ? "=>" : "  ";
153     PrintShadowBytes(prefix,
154                      (u8*)(aligned_shadow + i * n_bytes_per_row),
155                      (u8*)shadow_addr, n_bytes_per_row);
156   }
157   if (flags()->print_legend)
158     PrintLegend();
159 }
160 
PrintZoneForPointer(uptr ptr,uptr zone_ptr,const char * zone_name)161 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
162                                 const char *zone_name) {
163   if (zone_ptr) {
164     if (zone_name) {
165       Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
166                  ptr, zone_ptr, zone_name);
167     } else {
168       Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
169                  ptr, zone_ptr);
170     }
171   } else {
172     Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
173   }
174 }
175 
176 // ---------------------- Address Descriptions ------------------- {{{1
177 
IsASCII(unsigned char c)178 static bool IsASCII(unsigned char c) {
179   return /*0x00 <= c &&*/ c <= 0x7F;
180 }
181 
182 // Check if the global is a zero-terminated ASCII string. If so, print it.
PrintGlobalNameIfASCII(const __asan_global & g)183 static void PrintGlobalNameIfASCII(const __asan_global &g) {
184   for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
185     if (!IsASCII(*(unsigned char*)p)) return;
186   }
187   if (*(char*)(g.beg + g.size - 1) != 0) return;
188   Printf("  '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
189 }
190 
DescribeAddressRelativeToGlobal(uptr addr,uptr size,const __asan_global & g)191 bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
192                                      const __asan_global &g) {
193   static const uptr kMinimalDistanceFromAnotherGlobal = 64;
194   if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false;
195   if (addr >= g.beg + g.size_with_redzone) return false;
196   Decorator d;
197   Printf("%s", d.Location());
198   if (addr < g.beg) {
199     Printf("%p is located %zd bytes to the left", (void*)addr, g.beg - addr);
200   } else if (addr + size > g.beg + g.size) {
201     if (addr < g.beg + g.size)
202       addr = g.beg + g.size;
203     Printf("%p is located %zd bytes to the right", (void*)addr,
204            addr - (g.beg + g.size));
205   } else {
206     // Can it happen?
207     Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
208   }
209   Printf(" of global variable '%s' (0x%zx) of size %zu\n",
210              g.name, g.beg, g.size);
211   Printf("%s", d.EndLocation());
212   PrintGlobalNameIfASCII(g);
213   return true;
214 }
215 
DescribeAddressIfShadow(uptr addr)216 bool DescribeAddressIfShadow(uptr addr) {
217   if (AddrIsInMem(addr))
218     return false;
219   static const char kAddrInShadowReport[] =
220       "Address %p is located in the %s.\n";
221   if (AddrIsInShadowGap(addr)) {
222     Printf(kAddrInShadowReport, addr, "shadow gap area");
223     return true;
224   }
225   if (AddrIsInHighShadow(addr)) {
226     Printf(kAddrInShadowReport, addr, "high shadow area");
227     return true;
228   }
229   if (AddrIsInLowShadow(addr)) {
230     Printf(kAddrInShadowReport, addr, "low shadow area");
231     return true;
232   }
233   CHECK(0 && "Address is not in memory and not in shadow?");
234   return false;
235 }
236 
DescribeAddressIfStack(uptr addr,uptr access_size)237 bool DescribeAddressIfStack(uptr addr, uptr access_size) {
238   AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
239   if (!t) return false;
240   const sptr kBufSize = 4095;
241   char buf[kBufSize];
242   uptr offset = 0;
243   const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
244   // This string is created by the compiler and has the following form:
245   // "FunctioName n alloc_1 alloc_2 ... alloc_n"
246   // where alloc_i looks like "offset size len ObjectName ".
247   CHECK(frame_descr);
248   // Report the function name and the offset.
249   const char *name_end = internal_strchr(frame_descr, ' ');
250   CHECK(name_end);
251   buf[0] = 0;
252   internal_strncat(buf, frame_descr,
253                    Min(kBufSize,
254                        static_cast<sptr>(name_end - frame_descr)));
255   Decorator d;
256   Printf("%s", d.Location());
257   Printf("Address %p is located at offset %zu "
258              "in frame <%s> of T%d's stack:\n",
259              (void*)addr, offset, Demangle(buf), t->tid());
260   Printf("%s", d.EndLocation());
261   // Report the number of stack objects.
262   char *p;
263   uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
264   CHECK(n_objects > 0);
265   Printf("  This frame has %zu object(s):\n", n_objects);
266   // Report all objects in this frame.
267   for (uptr i = 0; i < n_objects; i++) {
268     uptr beg, size;
269     sptr len;
270     beg  = internal_simple_strtoll(p, &p, 10);
271     size = internal_simple_strtoll(p, &p, 10);
272     len  = internal_simple_strtoll(p, &p, 10);
273     if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
274       Printf("AddressSanitizer can't parse the stack frame "
275                  "descriptor: |%s|\n", frame_descr);
276       break;
277     }
278     p++;
279     buf[0] = 0;
280     internal_strncat(buf, p, Min(kBufSize, len));
281     p += len;
282     Printf("    [%zu, %zu) '%s'\n", beg, beg + size, buf);
283   }
284   Printf("HINT: this may be a false positive if your program uses "
285              "some custom stack unwind mechanism or swapcontext\n"
286              "      (longjmp and C++ exceptions *are* supported)\n");
287   DescribeThread(t->summary());
288   return true;
289 }
290 
DescribeAccessToHeapChunk(AsanChunkView chunk,uptr addr,uptr access_size)291 static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
292                                       uptr access_size) {
293   sptr offset;
294   Decorator d;
295   Printf("%s", d.Location());
296   if (chunk.AddrIsAtLeft(addr, access_size, &offset)) {
297     Printf("%p is located %zd bytes to the left of", (void*)addr, offset);
298   } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) {
299     if (offset < 0) {
300       addr -= offset;
301       offset = 0;
302     }
303     Printf("%p is located %zd bytes to the right of", (void*)addr, offset);
304   } else if (chunk.AddrIsInside(addr, access_size, &offset)) {
305     Printf("%p is located %zd bytes inside of", (void*)addr, offset);
306   } else {
307     Printf("%p is located somewhere around (this is AddressSanitizer bug!)",
308            (void*)addr);
309   }
310   Printf(" %zu-byte region [%p,%p)\n", chunk.UsedSize(),
311          (void*)(chunk.Beg()), (void*)(chunk.End()));
312   Printf("%s", d.EndLocation());
313 }
314 
315 // Return " (thread_name) " or an empty string if the name is empty.
ThreadNameWithParenthesis(AsanThreadSummary * t,char buff[],uptr buff_len)316 const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
317                                       uptr buff_len) {
318   const char *name = t->name();
319   if (*name == 0) return "";
320   buff[0] = 0;
321   internal_strncat(buff, " (", 3);
322   internal_strncat(buff, name, buff_len - 4);
323   internal_strncat(buff, ")", 2);
324   return buff;
325 }
326 
ThreadNameWithParenthesis(u32 tid,char buff[],uptr buff_len)327 const char *ThreadNameWithParenthesis(u32 tid, char buff[],
328                                       uptr buff_len) {
329   if (tid == kInvalidTid) return "";
330   AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid);
331   return ThreadNameWithParenthesis(t, buff, buff_len);
332 }
333 
DescribeHeapAddress(uptr addr,uptr access_size)334 void DescribeHeapAddress(uptr addr, uptr access_size) {
335   AsanChunkView chunk = FindHeapChunkByAddress(addr);
336   if (!chunk.IsValid()) return;
337   DescribeAccessToHeapChunk(chunk, addr, access_size);
338   CHECK(chunk.AllocTid() != kInvalidTid);
339   AsanThreadSummary *alloc_thread =
340       asanThreadRegistry().FindByTid(chunk.AllocTid());
341   StackTrace alloc_stack;
342   chunk.GetAllocStack(&alloc_stack);
343   AsanThread *t = asanThreadRegistry().GetCurrent();
344   CHECK(t);
345   char tname[128];
346   Decorator d;
347   if (chunk.FreeTid() != kInvalidTid) {
348     AsanThreadSummary *free_thread =
349         asanThreadRegistry().FindByTid(chunk.FreeTid());
350     Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
351            free_thread->tid(),
352            ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
353            d.EndAllocation());
354     StackTrace free_stack;
355     chunk.GetFreeStack(&free_stack);
356     PrintStack(&free_stack);
357     Printf("%spreviously allocated by thread T%d%s here:%s\n",
358            d.Allocation(), alloc_thread->tid(),
359            ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
360            d.EndAllocation());
361     PrintStack(&alloc_stack);
362     DescribeThread(t->summary());
363     DescribeThread(free_thread);
364     DescribeThread(alloc_thread);
365   } else {
366     Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
367            alloc_thread->tid(),
368            ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
369            d.EndAllocation());
370     PrintStack(&alloc_stack);
371     DescribeThread(t->summary());
372     DescribeThread(alloc_thread);
373   }
374 }
375 
DescribeAddress(uptr addr,uptr access_size)376 void DescribeAddress(uptr addr, uptr access_size) {
377   // Check if this is shadow or shadow gap.
378   if (DescribeAddressIfShadow(addr))
379     return;
380   CHECK(AddrIsInMem(addr));
381   if (DescribeAddressIfGlobal(addr, access_size))
382     return;
383   if (DescribeAddressIfStack(addr, access_size))
384     return;
385   // Assume it is a heap address.
386   DescribeHeapAddress(addr, access_size);
387 }
388 
389 // ------------------- Thread description -------------------- {{{1
390 
DescribeThread(AsanThreadSummary * summary)391 void DescribeThread(AsanThreadSummary *summary) {
392   CHECK(summary);
393   // No need to announce the main thread.
394   if (summary->tid() == 0 || summary->announced()) {
395     return;
396   }
397   summary->set_announced(true);
398   char tname[128];
399   Printf("Thread T%d%s", summary->tid(),
400          ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
401   Printf(" created by T%d%s here:\n",
402          summary->parent_tid(),
403          ThreadNameWithParenthesis(summary->parent_tid(),
404                                    tname, sizeof(tname)));
405   PrintStack(summary->stack());
406   // Recursively described parent thread if needed.
407   if (flags()->print_full_thread_history) {
408     AsanThreadSummary *parent_summary =
409         asanThreadRegistry().FindByTid(summary->parent_tid());
410     DescribeThread(parent_summary);
411   }
412 }
413 
414 // -------------------- Different kinds of reports ----------------- {{{1
415 
416 // Use ScopedInErrorReport to run common actions just before and
417 // immediately after printing error report.
418 class ScopedInErrorReport {
419  public:
ScopedInErrorReport()420   ScopedInErrorReport() {
421     static atomic_uint32_t num_calls;
422     static u32 reporting_thread_tid;
423     if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
424       // Do not print more than one report, otherwise they will mix up.
425       // Error reporting functions shouldn't return at this situation, as
426       // they are defined as no-return.
427       Report("AddressSanitizer: while reporting a bug found another one."
428                  "Ignoring.\n");
429       u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
430       if (current_tid != reporting_thread_tid) {
431         // ASan found two bugs in different threads simultaneously. Sleep
432         // long enough to make sure that the thread which started to print
433         // an error report will finish doing it.
434         SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
435       }
436       // If we're still not dead for some reason, use raw _exit() instead of
437       // Die() to bypass any additional checks.
438       internal__exit(flags()->exitcode);
439     }
440     ASAN_ON_ERROR();
441     reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
442     Printf("===================================================="
443            "=============\n");
444     if (reporting_thread_tid != kInvalidTid) {
445       // We started reporting an error message. Stop using the fake stack
446       // in case we call an instrumented function from a symbolizer.
447       AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
448       CHECK(curr_thread);
449       curr_thread->fake_stack().StopUsingFakeStack();
450     }
451   }
452   // Destructor is NORETURN, as functions that report errors are.
~ScopedInErrorReport()453   NORETURN ~ScopedInErrorReport() {
454     // Make sure the current thread is announced.
455     AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
456     if (curr_thread) {
457       DescribeThread(curr_thread->summary());
458     }
459     // Print memory stats.
460     if (flags()->print_stats)
461       __asan_print_accumulated_stats();
462     if (error_report_callback) {
463       error_report_callback(error_message_buffer);
464     }
465     Report("ABORTING\n");
466     Die();
467   }
468 };
469 
ReportSummary(const char * error_type,StackTrace * stack)470 static void ReportSummary(const char *error_type, StackTrace *stack) {
471   if (!stack->size) return;
472   if (IsSymbolizerAvailable()) {
473     AddressInfo ai;
474     // Currently, we include the first stack frame into the report summary.
475     // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
476     SymbolizeCode(stack->trace[0], &ai, 1);
477     ReportErrorSummary(error_type,
478                        StripPathPrefix(ai.file, flags()->strip_path_prefix),
479                        ai.line, ai.function);
480   }
481   // FIXME: do we need to print anything at all if there is no symbolizer?
482 }
483 
ReportSIGSEGV(uptr pc,uptr sp,uptr bp,uptr addr)484 void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
485   ScopedInErrorReport in_report;
486   Decorator d;
487   Printf("%s", d.Warning());
488   Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
489              " (pc %p sp %p bp %p T%d)\n",
490              (void*)addr, (void*)pc, (void*)sp, (void*)bp,
491              asanThreadRegistry().GetCurrentTidOrInvalid());
492   Printf("%s", d.EndWarning());
493   Printf("AddressSanitizer can not provide additional info.\n");
494   GET_STACK_TRACE_FATAL(pc, bp);
495   PrintStack(&stack);
496   ReportSummary("SEGV", &stack);
497 }
498 
ReportDoubleFree(uptr addr,StackTrace * stack)499 void ReportDoubleFree(uptr addr, StackTrace *stack) {
500   ScopedInErrorReport in_report;
501   Decorator d;
502   Printf("%s", d.Warning());
503   Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
504   Printf("%s", d.EndWarning());
505   PrintStack(stack);
506   DescribeHeapAddress(addr, 1);
507   ReportSummary("double-free", stack);
508 }
509 
ReportFreeNotMalloced(uptr addr,StackTrace * stack)510 void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
511   ScopedInErrorReport in_report;
512   Decorator d;
513   Printf("%s", d.Warning());
514   Report("ERROR: AddressSanitizer: attempting free on address "
515              "which was not malloc()-ed: %p\n", addr);
516   Printf("%s", d.EndWarning());
517   PrintStack(stack);
518   DescribeHeapAddress(addr, 1);
519   ReportSummary("bad-free", stack);
520 }
521 
ReportAllocTypeMismatch(uptr addr,StackTrace * stack,AllocType alloc_type,AllocType dealloc_type)522 void ReportAllocTypeMismatch(uptr addr, StackTrace *stack,
523                              AllocType alloc_type,
524                              AllocType dealloc_type) {
525   static const char *alloc_names[] =
526     {"INVALID", "malloc", "operator new", "operator new []"};
527   static const char *dealloc_names[] =
528     {"INVALID", "free", "operator delete", "operator delete []"};
529   CHECK_NE(alloc_type, dealloc_type);
530   ScopedInErrorReport in_report;
531   Decorator d;
532   Printf("%s", d.Warning());
533   Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
534         alloc_names[alloc_type], dealloc_names[dealloc_type], addr);
535   Printf("%s", d.EndWarning());
536   PrintStack(stack);
537   DescribeHeapAddress(addr, 1);
538   ReportSummary("alloc-dealloc-mismatch", stack);
539   Report("HINT: if you don't care about these warnings you may set "
540          "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
541 }
542 
ReportMallocUsableSizeNotOwned(uptr addr,StackTrace * stack)543 void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) {
544   ScopedInErrorReport in_report;
545   Decorator d;
546   Printf("%s", d.Warning());
547   Report("ERROR: AddressSanitizer: attempting to call "
548              "malloc_usable_size() for pointer which is "
549              "not owned: %p\n", addr);
550   Printf("%s", d.EndWarning());
551   PrintStack(stack);
552   DescribeHeapAddress(addr, 1);
553   ReportSummary("bad-malloc_usable_size", stack);
554 }
555 
ReportAsanGetAllocatedSizeNotOwned(uptr addr,StackTrace * stack)556 void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) {
557   ScopedInErrorReport in_report;
558   Decorator d;
559   Printf("%s", d.Warning());
560   Report("ERROR: AddressSanitizer: attempting to call "
561              "__asan_get_allocated_size() for pointer which is "
562              "not owned: %p\n", addr);
563   Printf("%s", d.EndWarning());
564   PrintStack(stack);
565   DescribeHeapAddress(addr, 1);
566   ReportSummary("bad-__asan_get_allocated_size", stack);
567 }
568 
ReportStringFunctionMemoryRangesOverlap(const char * function,const char * offset1,uptr length1,const char * offset2,uptr length2,StackTrace * stack)569 void ReportStringFunctionMemoryRangesOverlap(
570     const char *function, const char *offset1, uptr length1,
571     const char *offset2, uptr length2, StackTrace *stack) {
572   ScopedInErrorReport in_report;
573   Decorator d;
574   char bug_type[100];
575   internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function);
576   Printf("%s", d.Warning());
577   Report("ERROR: AddressSanitizer: %s: "
578              "memory ranges [%p,%p) and [%p, %p) overlap\n", \
579              bug_type, offset1, offset1 + length1, offset2, offset2 + length2);
580   Printf("%s", d.EndWarning());
581   PrintStack(stack);
582   DescribeAddress((uptr)offset1, length1);
583   DescribeAddress((uptr)offset2, length2);
584   ReportSummary(bug_type, stack);
585 }
586 
587 // ----------------------- Mac-specific reports ----------------- {{{1
588 
WarnMacFreeUnallocated(uptr addr,uptr zone_ptr,const char * zone_name,StackTrace * stack)589 void WarnMacFreeUnallocated(
590     uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
591   // Just print a warning here.
592   Printf("free_common(%p) -- attempting to free unallocated memory.\n"
593              "AddressSanitizer is ignoring this error on Mac OS now.\n",
594              addr);
595   PrintZoneForPointer(addr, zone_ptr, zone_name);
596   PrintStack(stack);
597   DescribeHeapAddress(addr, 1);
598 }
599 
ReportMacMzReallocUnknown(uptr addr,uptr zone_ptr,const char * zone_name,StackTrace * stack)600 void ReportMacMzReallocUnknown(
601     uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
602   ScopedInErrorReport in_report;
603   Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
604              "This is an unrecoverable problem, exiting now.\n",
605              addr);
606   PrintZoneForPointer(addr, zone_ptr, zone_name);
607   PrintStack(stack);
608   DescribeHeapAddress(addr, 1);
609 }
610 
ReportMacCfReallocUnknown(uptr addr,uptr zone_ptr,const char * zone_name,StackTrace * stack)611 void ReportMacCfReallocUnknown(
612     uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) {
613   ScopedInErrorReport in_report;
614   Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
615              "This is an unrecoverable problem, exiting now.\n",
616              addr);
617   PrintZoneForPointer(addr, zone_ptr, zone_name);
618   PrintStack(stack);
619   DescribeHeapAddress(addr, 1);
620 }
621 
622 }  // namespace __asan
623 
624 // --------------------------- Interface --------------------- {{{1
625 using namespace __asan;  // NOLINT
626 
__asan_report_error(uptr pc,uptr bp,uptr sp,uptr addr,bool is_write,uptr access_size)627 void __asan_report_error(uptr pc, uptr bp, uptr sp,
628                          uptr addr, bool is_write, uptr access_size) {
629   ScopedInErrorReport in_report;
630 
631   // Determine the error type.
632   const char *bug_descr = "unknown-crash";
633   if (AddrIsInMem(addr)) {
634     u8 *shadow_addr = (u8*)MemToShadow(addr);
635     // If we are accessing 16 bytes, look at the second shadow byte.
636     if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
637       shadow_addr++;
638     // If we are in the partial right redzone, look at the next shadow byte.
639     if (*shadow_addr > 0 && *shadow_addr < 128)
640       shadow_addr++;
641     switch (*shadow_addr) {
642       case kAsanHeapLeftRedzoneMagic:
643       case kAsanHeapRightRedzoneMagic:
644         bug_descr = "heap-buffer-overflow";
645         break;
646       case kAsanHeapFreeMagic:
647         bug_descr = "heap-use-after-free";
648         break;
649       case kAsanStackLeftRedzoneMagic:
650         bug_descr = "stack-buffer-underflow";
651         break;
652       case kAsanInitializationOrderMagic:
653         bug_descr = "initialization-order-fiasco";
654         break;
655       case kAsanStackMidRedzoneMagic:
656       case kAsanStackRightRedzoneMagic:
657       case kAsanStackPartialRedzoneMagic:
658         bug_descr = "stack-buffer-overflow";
659         break;
660       case kAsanStackAfterReturnMagic:
661         bug_descr = "stack-use-after-return";
662         break;
663       case kAsanUserPoisonedMemoryMagic:
664         bug_descr = "use-after-poison";
665         break;
666       case kAsanStackUseAfterScopeMagic:
667         bug_descr = "stack-use-after-scope";
668         break;
669       case kAsanGlobalRedzoneMagic:
670         bug_descr = "global-buffer-overflow";
671         break;
672     }
673   }
674   Decorator d;
675   Printf("%s", d.Warning());
676   Report("ERROR: AddressSanitizer: %s on address "
677              "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
678              bug_descr, (void*)addr, pc, bp, sp);
679   Printf("%s", d.EndWarning());
680 
681   u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
682   char tname[128];
683   Printf("%s%s of size %zu at %p thread T%d%s%s\n",
684          d.Access(),
685          access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
686          access_size, (void*)addr, curr_tid,
687          ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
688          d.EndAccess());
689 
690   GET_STACK_TRACE_FATAL(pc, bp);
691   PrintStack(&stack);
692 
693   DescribeAddress(addr, access_size);
694   ReportSummary(bug_descr, &stack);
695   PrintShadowMemoryForAddress(addr);
696 }
697 
__asan_set_error_report_callback(void (* callback)(const char *))698 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
699   error_report_callback = callback;
700   if (callback) {
701     error_message_buffer_size = 1 << 16;
702     error_message_buffer =
703         (char*)MmapOrDie(error_message_buffer_size, __FUNCTION__);
704     error_message_buffer_pos = 0;
705   }
706 }
707 
__asan_describe_address(uptr addr)708 void __asan_describe_address(uptr addr) {
709   DescribeAddress(addr, 1);
710 }
711 
712 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
713 // Provide default implementation of __asan_on_error that does nothing
714 // and may be overriden by user.
715 SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
__asan_on_error()716 void __asan_on_error() {}
717 #endif
718