asan_report.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===-- asan_report.cc ----------------------------------------------------===// 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The LLVM Compiler Infrastructure 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file is distributed under the University of Illinois Open Source 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// License. See LICENSE.TXT for details. 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===// 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file is a part of AddressSanitizer, an address sanity checker. 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file contains error reporting code. 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===// 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_flags.h" 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_internal.h" 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_mapping.h" 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_report.h" 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_stack.h" 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "asan_thread.h" 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sanitizer_common/sanitizer_common.h" 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sanitizer_common/sanitizer_flags.h" 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sanitizer_common/sanitizer_report_decorator.h" 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sanitizer_common/sanitizer_stackdepot.h" 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "sanitizer_common/sanitizer_symbolizer.h" 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace __asan { 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// -------------------- User-specified callbacks ----------------- {{{1 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void (*error_report_callback)(const char*); 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic char *error_message_buffer = 0; 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic uptr error_message_buffer_pos = 0; 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic uptr error_message_buffer_size = 0; 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid AppendToErrorMessageBuffer(const char *buffer) { 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (error_message_buffer) { 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr length = internal_strlen(buffer); 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_GE(error_message_buffer_size, error_message_buffer_pos); 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr remaining = error_message_buffer_size - error_message_buffer_pos; 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_strncpy(error_message_buffer + error_message_buffer_pos, 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buffer, remaining); 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_message_buffer[error_message_buffer_size - 1] = '\0'; 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // FIXME: reallocate the buffer instead of truncating the message. 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_message_buffer_pos += remaining > length ? length : remaining; 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ---------------------- Decorator ------------------------------ {{{1 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass Decorator: public __sanitizer::SanitizerCommonDecorator { 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator() : SanitizerCommonDecorator() { } 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *Access() { return Blue(); } 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *EndAccess() { return Default(); } 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *Location() { return Green(); } 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *EndLocation() { return Default(); } 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *Allocation() { return Magenta(); } 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *EndAllocation() { return Default(); } 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *ShadowByte(u8 byte) { 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (byte) { 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapLeftRedzoneMagic: 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapRightRedzoneMagic: 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Red(); 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapFreeMagic: 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Magenta(); 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackLeftRedzoneMagic: 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackMidRedzoneMagic: 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackRightRedzoneMagic: 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackPartialRedzoneMagic: 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Red(); 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackAfterReturnMagic: 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Magenta(); 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanInitializationOrderMagic: 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Cyan(); 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanUserPoisonedMemoryMagic: 75457812d99a213dedf1c4cd38018ff48118d0c44fthakis@chromium.org case kAsanContiguousContainerOOBMagic: 76457812d99a213dedf1c4cd38018ff48118d0c44fthakis@chromium.org return Blue(); 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackUseAfterScopeMagic: 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Magenta(); 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanGlobalRedzoneMagic: 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Red(); 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanInternalHeapMagic: 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Yellow(); 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return Default(); 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *EndShadowByte() { return Default(); } 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ---------------------- Helper functions ----------------------- {{{1 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintShadowByte(InternalScopedString *str, const char *before, 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u8 byte, const char *after = "\n") { 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append("%s%s%x%x%s%s", before, d.ShadowByte(byte), byte >> 4, byte & 15, 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.EndShadowByte(), after); 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintShadowBytes(InternalScopedString *str, const char *before, 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u8 *bytes, u8 *guilty, uptr n) { 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (before) str->append("%s%p:", before, bytes); 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (uptr i = 0; i < n; i++) { 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u8 *p = bytes + i; 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *before = 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " "; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *after = p == guilty ? "]" : ""; 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, before, *p, after); 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append("\n"); 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintLegend(InternalScopedString *str) { 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append( 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Shadow byte legend (one shadow byte represents %d " 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "application bytes):\n", 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (int)SHADOW_GRANULARITY); 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Addressable: ", 0); 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append(" Partially addressable: "); 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append("\n"); 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Heap left redzone: ", 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanHeapLeftRedzoneMagic); 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Heap right redzone: ", 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanHeapRightRedzoneMagic); 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic); 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack left redzone: ", 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackLeftRedzoneMagic); 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack mid redzone: ", 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackMidRedzoneMagic); 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack right redzone: ", 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackRightRedzoneMagic); 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack partial redzone: ", 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackPartialRedzoneMagic); 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack after return: ", 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackAfterReturnMagic); 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Stack use after scope: ", 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanStackUseAfterScopeMagic); 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic); 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Global init order: ", 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanInitializationOrderMagic); 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Poisoned by user: ", 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanUserPoisonedMemoryMagic); 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " Container overflow: ", 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kAsanContiguousContainerOOBMagic); 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintShadowMemoryForAddress(uptr addr) { 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!AddrIsInMem(addr)) return; 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr shadow_addr = MemToShadow(addr); 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const uptr n_bytes_per_row = 16; 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedString str(4096 * 8); 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("Shadow bytes around the buggy address:\n"); 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (int i = -5; i <= 5; i++) { 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *prefix = (i == 0) ? "=>" : " "; 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row), 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (u8 *)shadow_addr, n_bytes_per_row); 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (flags()->print_legend) PrintLegend(&str); 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", str.data()); 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintZoneForPointer(uptr ptr, uptr zone_ptr, 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *zone_name) { 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (zone_ptr) { 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (zone_name) { 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n", 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr, zone_ptr, zone_name); 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n", 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ptr, zone_ptr); 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("malloc_zone_from_ptr(%p) = 0\n", ptr); 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void DescribeThread(AsanThread *t) { 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (t) 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(t->context()); 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ---------------------- Address Descriptions ------------------- {{{1 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool IsASCII(unsigned char c) { 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return /*0x00 <= c &&*/ c <= 0x7F; 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *MaybeDemangleGlobalName(const char *name) { 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We can spoil names of globals with C linkage, so use an heuristic 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // approach to check if the name should be demangled. 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool should_demangle = false; 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (name[0] == '_' && name[1] == 'Z') 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org should_demangle = true; 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (SANITIZER_WINDOWS && name[0] == '\01' && name[1] == '?') 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org should_demangle = true; 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return should_demangle ? Symbolizer::Get()->Demangle(name) : name; 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Check if the global is a zero-terminated ASCII string. If so, print it. 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void PrintGlobalNameIfASCII(InternalScopedString *str, 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const __asan_global &g) { 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (uptr p = g.beg; p < g.beg + g.size - 1; p++) { 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned char c = *(unsigned char*)p; 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (c == '\0' || !IsASCII(c)) return; 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*(char*)(g.beg + g.size - 1) != '\0') return; 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str->append(" '%s' is ascii string '%s'\n", MaybeDemangleGlobalName(g.name), 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (char *)g.beg); 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool DescribeAddressRelativeToGlobal(uptr addr, uptr size, 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const __asan_global &g) { 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const uptr kMinimalDistanceFromAnotherGlobal = 64; 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr <= g.beg - kMinimalDistanceFromAnotherGlobal) return false; 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr >= g.beg + g.size_with_redzone) return false; 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedString str(4096); 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%s", d.Location()); 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr < g.beg) { 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes to the left", (void *)addr, 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org g.beg - addr); 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (addr + size > g.beg + g.size) { 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr < g.beg + g.size) 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr = g.beg + g.size; 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes to the right", (void *)addr, 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr - (g.beg + g.size)); 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Can it happen? 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg); 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append(" of global variable '%s' from '%s' (0x%zx) of size %zu\n", 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org MaybeDemangleGlobalName(g.name), g.module_name, g.beg, g.size); 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%s", d.EndLocation()); 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintGlobalNameIfASCII(&str, g); 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", str.data()); 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool DescribeAddressIfShadow(uptr addr) { 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AddrIsInMem(addr)) 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char kAddrInShadowReport[] = 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Address %p is located in the %s.\n"; 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AddrIsInShadowGap(addr)) { 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(kAddrInShadowReport, addr, "shadow gap area"); 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AddrIsInHighShadow(addr)) { 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(kAddrInShadowReport, addr, "high shadow area"); 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AddrIsInLowShadow(addr)) { 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(kAddrInShadowReport, addr, "low shadow area"); 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK(0 && "Address is not in memory and not in shadow?"); 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Return " (thread_name) " or an empty string if the name is empty. 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[], 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr buff_len) { 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name = t->name; 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (name[0] == '\0') return ""; 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buff[0] = 0; 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_strncat(buff, " (", 3); 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_strncat(buff, name, buff_len - 4); 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_strncat(buff, ")", 2); 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return buff; 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst char *ThreadNameWithParenthesis(u32 tid, char buff[], 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr buff_len) { 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (tid == kInvalidTid) return ""; 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org asanThreadRegistry().CheckLocked(); 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanThreadContext *t = GetThreadContextByTidLocked(tid); 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ThreadNameWithParenthesis(t, buff, buff_len); 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid PrintAccessAndVarIntersection(const char *var_name, 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr var_beg, uptr var_size, 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr addr, uptr access_size, 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr prev_var_end, uptr next_var_beg) { 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr var_end = var_beg + var_size; 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr addr_end = addr + access_size; 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *pos_descr = 0; 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // If the variable [var_beg, var_end) is the nearest variable to the 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // current memory access, indicate it in the log. 293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr >= var_beg) { 294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr_end <= var_end) 295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pos_descr = "is inside"; // May happen if this is a use-after-return. 296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (addr < var_end) 297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pos_descr = "partially overflows"; 298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (addr_end <= next_var_beg && 299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org next_var_beg - addr_end >= addr - var_end) 300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pos_descr = "overflows"; 301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (addr_end > var_beg) 303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pos_descr = "partially underflows"; 304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else if (addr >= prev_var_end && 305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr - prev_var_end >= var_beg - addr_end) 306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org pos_descr = "underflows"; 307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedString str(1024); 309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append(" [%zd, %zd) '%s'", var_beg, var_beg + var_size, var_name); 310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (pos_descr) { 311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // FIXME: we may want to also print the size of the access here, 313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // but in case of accesses generated by memset it may be confusing. 314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%s <== Memory access at offset %zd %s this variable%s\n", 315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.Location(), addr, pos_descr, d.EndLocation()); 316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("\n"); 318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", str.data()); 320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct StackVarDescr { 323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr beg; 324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr size; 325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name_pos; 326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr name_len; 327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool DescribeAddressIfStack(uptr addr, uptr access_size) { 330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanThread *t = FindThreadByStackAddress(addr); 331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!t) return false; 332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const uptr kBufSize = 4095; 333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char buf[kBufSize]; 334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr offset = 0; 335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr frame_pc = 0; 336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc); 338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef __powerpc64__ 340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // On PowerPC64, the address of a function actually points to a 341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // three-doubleword data structure with the first field containing 342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // the address of the function's code. 343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org frame_pc = *reinterpret_cast<uptr *>(frame_pc); 344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // This string is created by the compiler and has the following form: 347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // "n alloc_1 alloc_2 ... alloc_n" 348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // where alloc_i looks like "offset size len ObjectName ". 349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK(frame_descr); 350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Location()); 352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("Address %p is located in stack of thread T%d%s " 353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "at offset %zu in frame\n", 354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr, t->tid(), 355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname)), 356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org offset); 357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Now we print the frame where the alloca has happened. 358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We print this frame as a stack trace with one element. 359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The symbolizer may print more than one frame if inlining was involved. 360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // The frame numbers may be different than those in the stack trace printed 361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // previously. That's unfortunate, but I have no better solution, 362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // especially given that the alloca may be from entirely different place 363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // (e.g. use-after-scope, or different thread's stack). 364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace alloca_stack; 365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloca_stack.trace[0] = frame_pc + 16; 366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloca_stack.size = 1; 367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndLocation()); 368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloca_stack.Print(); 369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Report the number of stack objects. 370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char *p; 371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10); 372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_GT(n_objects, 0); 373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(" This frame has %zu object(s):\n", n_objects); 374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Report all objects in this frame. 376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedBuffer<StackVarDescr> vars(n_objects); 377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (uptr i = 0; i < n_objects; i++) { 378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr beg, size; 379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr len; 380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org beg = (uptr)internal_simple_strtoll(p, &p, 10); 381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size = (uptr)internal_simple_strtoll(p, &p, 10); 382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org len = (uptr)internal_simple_strtoll(p, &p, 10); 383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (beg == 0 || size == 0 || *p != ' ') { 384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("AddressSanitizer can't parse the stack frame " 385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "descriptor: |%s|\n", frame_descr); 386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p++; 389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vars[i].beg = beg; 390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vars[i].size = size; 391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vars[i].name_pos = p; 392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org vars[i].name_len = len; 393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org p += len; 394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (uptr i = 0; i < n_objects; i++) { 396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org buf[0] = 0; 397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_strncat(buf, vars[i].name_pos, 398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static_cast<uptr>(Min(kBufSize, vars[i].name_len))); 399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0; 400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL); 401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintAccessAndVarIntersection(buf, vars[i].beg, vars[i].size, 402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org offset, access_size, 403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org prev_var_end, next_var_beg); 404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("HINT: this may be a false positive if your program uses " 406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "some custom stack unwind mechanism or swapcontext\n" 407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " (longjmp and C++ exceptions *are* supported)\n"); 408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(t); 409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr, 413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr access_size) { 414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org sptr offset; 415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedString str(4096); 417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%s", d.Location()); 418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (chunk.AddrIsAtLeft(addr, access_size, &offset)) { 419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes to the left of", (void *)addr, offset); 420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (chunk.AddrIsAtRight(addr, access_size, &offset)) { 421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (offset < 0) { 422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr -= offset; 423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org offset = 0; 424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes to the right of", (void *)addr, offset); 426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else if (chunk.AddrIsInside(addr, access_size, &offset)) { 427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located %zd bytes inside of", (void*)addr, offset); 428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%p is located somewhere around (this is AddressSanitizer bug!)", 430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (void *)addr); 431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append(" %zu-byte region [%p,%p)\n", chunk.UsedSize(), 433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (void *)(chunk.Beg()), (void *)(chunk.End())); 434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("%s", d.EndLocation()); 435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", str.data()); 436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid DescribeHeapAddress(uptr addr, uptr access_size) { 439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanChunkView chunk = FindHeapChunkByAddress(addr); 440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!chunk.IsValid()) { 441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("AddressSanitizer can not describe address in more detail " 442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "(wild memory access suspected).\n"); 443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAccessToHeapChunk(chunk, addr, access_size); 446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK(chunk.AllocTid() != kInvalidTid); 447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org asanThreadRegistry().CheckLocked(); 448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanThreadContext *alloc_thread = 449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetThreadContextByTidLocked(chunk.AllocTid()); 450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace alloc_stack; 451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org chunk.GetAllocStack(&alloc_stack); 452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanThreadContext *free_thread = 0; 455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (chunk.FreeTid() != kInvalidTid) { 456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free_thread = GetThreadContextByTidLocked(chunk.FreeTid()); 457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(), 458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free_thread->tid, 459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)), 460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.EndAllocation()); 461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace free_stack; 462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org chunk.GetFreeStack(&free_stack); 463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org free_stack.Print(); 464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%spreviously allocated by thread T%d%s here:%s\n", 465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.Allocation(), alloc_thread->tid, 466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.EndAllocation()); 468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(), 470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc_thread->tid, 471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)), 472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.EndAllocation()); 473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc_stack.Print(); 475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(GetCurrentThread()); 476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (free_thread) 477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(free_thread); 478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(alloc_thread); 479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid DescribeAddress(uptr addr, uptr access_size) { 482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Check if this is shadow or shadow gap. 483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DescribeAddressIfShadow(addr)) 484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK(AddrIsInMem(addr)); 486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DescribeAddressIfGlobal(addr, access_size)) 487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DescribeAddressIfStack(addr, access_size)) 489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Assume it is a heap address. 491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, access_size); 492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ------------------- Thread description -------------------- {{{1 495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid DescribeThread(AsanThreadContext *context) { 497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK(context); 498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org asanThreadRegistry().CheckLocked(); 499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // No need to announce the main thread. 500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (context->tid == 0 || context->announced) { 501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org context->announced = true; 504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org InternalScopedString str(1024); 506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append("Thread T%d%s", context->tid, 507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(context->tid, tname, sizeof(tname))); 508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org str.append( 509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " created by T%d%s here:\n", context->parent_tid, 510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(context->parent_tid, tname, sizeof(tname))); 511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", str.data()); 512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr stack_size; 513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const uptr *stack_trace = StackDepotGet(context->stack_id, &stack_size); 514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace::PrintStack(stack_trace, stack_size); 515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Recursively described parent thread if needed. 516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (flags()->print_full_thread_history) { 517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanThreadContext *parent_context = 518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetThreadContextByTidLocked(context->parent_tid); 519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(parent_context); 520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// -------------------- Different kinds of reports ----------------- {{{1 524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Use ScopedInErrorReport to run common actions just before and 526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// immediately after printing error report. 527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ScopedInErrorReport { 528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport() { 530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static atomic_uint32_t num_calls; 531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static u32 reporting_thread_tid; 532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Do not print more than one report, otherwise they will mix up. 534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Error reporting functions shouldn't return at this situation, as 535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // they are defined as no-return. 536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("AddressSanitizer: while reporting a bug found another one." 537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Ignoring.\n"); 538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u32 current_tid = GetCurrentTidOrInvalid(); 539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (current_tid != reporting_thread_tid) { 540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ASan found two bugs in different threads simultaneously. Sleep 541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // long enough to make sure that the thread which started to print 542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // an error report will finish doing it. 543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); 544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // If we're still not dead for some reason, use raw _exit() instead of 546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Die() to bypass any additional checks. 547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal__exit(flags()->exitcode); 548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ASAN_ON_ERROR(); 550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Make sure the registry and sanitizer report mutexes are locked while 551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // we're printing an error report. 552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We can lock them only here to avoid self-deadlock in case of 553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // recursive reports. 554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org asanThreadRegistry().Lock(); 555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CommonSanitizerReportMutex.Lock(); 556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org reporting_thread_tid = GetCurrentTidOrInvalid(); 557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("====================================================" 558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "=============\n"); 559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Destructor is NORETURN, as functions that report errors are. 561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org NORETURN ~ScopedInErrorReport() { 562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Make sure the current thread is announced. 563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeThread(GetCurrentThread()); 564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We may want to grab this lock again when printing stats. 565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org asanThreadRegistry().Unlock(); 566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Print memory stats. 567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (flags()->print_stats) 568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org __asan_print_accumulated_stats(); 569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (error_report_callback) { 570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_report_callback(error_message_buffer); 571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ABORTING\n"); 573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Die(); 574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) { 578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report( 582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "ERROR: AddressSanitizer: stack-overflow on address %p" 583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " (pc %p sp %p bp %p T%d)\n", 584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (void *)addr, (void *)pc, (void *)sp, (void *)bp, 585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetCurrentTidOrInvalid()); 586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_SIGNAL(pc, bp, context); 588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("stack-overflow", &stack); 590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr) { 593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report( 597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "ERROR: AddressSanitizer: SEGV on unknown address %p" 598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " (pc %p sp %p bp %p T%d)\n", 599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (void *)addr, (void *)pc, (void *)sp, (void *)bp, 600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GetCurrentTidOrInvalid()); 601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_SIGNAL(pc, bp, context); 603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("AddressSanitizer can not provide additional info.\n"); 605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("SEGV", &stack); 606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportDoubleFree(uptr addr, StackTrace *free_stack) { 609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u32 curr_tid = GetCurrentTidOrInvalid(); 614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: attempting double-free on %p in " 615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "thread T%d%s:\n", 616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr, curr_tid, 617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); 618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_GT(free_stack->size, 0); 620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("double-free", &stack); 624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportFreeNotMalloced(uptr addr, StackTrace *free_stack) { 627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u32 curr_tid = GetCurrentTidOrInvalid(); 632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: attempting free on address " 633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "which was not malloc()-ed: %p in thread T%d%s\n", addr, 634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname))); 635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_GT(free_stack->size, 0); 637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("bad-free", &stack); 641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportAllocTypeMismatch(uptr addr, StackTrace *free_stack, 644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AllocType alloc_type, 645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AllocType dealloc_type) { 646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char *alloc_names[] = 647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"INVALID", "malloc", "operator new", "operator new []"}; 648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const char *dealloc_names[] = 649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org {"INVALID", "free", "operator delete", "operator delete []"}; 650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_NE(alloc_type, dealloc_type); 651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n", 655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc_names[alloc_type], dealloc_names[dealloc_type], addr); 656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CHECK_GT(free_stack->size, 0); 658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("alloc-dealloc-mismatch", &stack); 662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("HINT: if you don't care about these warnings you may set " 663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); 664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) { 667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: attempting to call " 671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "malloc_usable_size() for pointer which is " 672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "not owned: %p\n", addr); 673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("bad-malloc_usable_size", stack); 677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { 680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: attempting to call " 684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "__asan_get_allocated_size() for pointer which is " 685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "not owned: %p\n", addr); 686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("bad-__asan_get_allocated_size", stack); 690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportStringFunctionMemoryRangesOverlap( 693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *function, const char *offset1, uptr length1, 694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *offset2, uptr length2, StackTrace *stack) { 695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char bug_type[100]; 698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: %s: " 701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "memory ranges [%p,%p) and [%p, %p) overlap\n", \ 702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_type, offset1, offset1 + length1, offset2, offset2 + length2); 703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress((uptr)offset1, length1); 706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress((uptr)offset2, length2); 707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary(bug_type, stack); 708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportStringFunctionSizeOverflow(uptr offset, uptr size, 711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace *stack) { 712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *bug_type = "negative-size-param"; 715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size); 717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress(offset, size); 720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary(bug_type, stack); 721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end, 724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr old_mid, uptr new_mid, 725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackTrace *stack) { 726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: bad parameters to " 728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "__sanitizer_annotate_contiguous_container:\n" 729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " beg : %p\n" 730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " end : %p\n" 731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " old_mid : %p\n" 732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org " new_mid : %p\n", 733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org beg, end, old_mid, new_mid); 734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack); 736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportODRViolation(const __asan_global *g1, const __asan_global *g2) { 739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg); 743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name); 745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name); 746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("HINT: if you don't care about these warnings you may set " 747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "ASAN_OPTIONS=detect_odr_violation=0\n"); 748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name); 749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ----------------------- CheckForInvalidPointerPair ----------- {{{1 752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic NOINLINE void 753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgReportInvalidPointerPair(uptr pc, uptr bp, uptr sp, uptr a1, uptr a2) { 754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n", a1, a2); 758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_FATAL(pc, bp); 760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress(a1, 1); 762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress(a2, 1); 763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary("invalid-pointer-pair", &stack); 764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void CheckForInvalidPointerPair(void *p1, void *p2) { 767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!flags()->detect_invalid_pointer_pairs) return; 768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr a1 = reinterpret_cast<uptr>(p1); 769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr a2 = reinterpret_cast<uptr>(p2); 770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanChunkView chunk1 = FindHeapChunkByAddress(a1); 771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AsanChunkView chunk2 = FindHeapChunkByAddress(a2); 772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool valid1 = chunk1.IsValid(); 773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool valid2 = chunk2.IsValid(); 774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if ((valid1 != valid2) || (valid1 && valid2 && !chunk1.Eq(chunk2))) { 775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_CALLER_PC_BP_SP; \ 776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return ReportInvalidPointerPair(pc, bp, sp, a1, a2); 777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// ----------------------- Mac-specific reports ----------------- {{{1 780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid WarnMacFreeUnallocated( 782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Just print a warning here. 784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("free_common(%p) -- attempting to free unallocated memory.\n" 785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "AddressSanitizer is ignoring this error on Mac OS now.\n", 786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr); 787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintZoneForPointer(addr, zone_ptr, zone_name); 788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportMacMzReallocUnknown( 793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n" 796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "This is an unrecoverable problem, exiting now.\n", 797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr); 798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintZoneForPointer(addr, zone_ptr, zone_name); 799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid ReportMacCfReallocUnknown( 804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr addr, uptr zone_ptr, const char *zone_name, StackTrace *stack) { 805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n" 807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "This is an unrecoverable problem, exiting now.\n", 808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org addr); 809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintZoneForPointer(addr, zone_ptr, zone_name); 810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack->Print(); 811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeHeapAddress(addr, 1); 812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // namespace __asan 815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// --------------------------- Interface --------------------- {{{1 817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace __asan; // NOLINT 818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write, 820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uptr access_size) { 821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ScopedInErrorReport in_report; 822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Determine the error type. 824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *bug_descr = "unknown-crash"; 825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AddrIsInMem(addr)) { 826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u8 *shadow_addr = (u8*)MemToShadow(addr); 827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // If we are accessing 16 bytes, look at the second shadow byte. 828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) 829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shadow_addr++; 830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // If we are in the partial right redzone, look at the next shadow byte. 831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (*shadow_addr > 0 && *shadow_addr < 128) 832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org shadow_addr++; 833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (*shadow_addr) { 834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapLeftRedzoneMagic: 835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapRightRedzoneMagic: 836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "heap-buffer-overflow"; 837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanHeapFreeMagic: 839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "heap-use-after-free"; 840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackLeftRedzoneMagic: 842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "stack-buffer-underflow"; 843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanInitializationOrderMagic: 845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "initialization-order-fiasco"; 846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackMidRedzoneMagic: 848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackRightRedzoneMagic: 849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackPartialRedzoneMagic: 850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "stack-buffer-overflow"; 851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackAfterReturnMagic: 853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "stack-use-after-return"; 854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanUserPoisonedMemoryMagic: 856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "use-after-poison"; 857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanContiguousContainerOOBMagic: 859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "container-overflow"; 860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanStackUseAfterScopeMagic: 862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "stack-use-after-scope"; 863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case kAsanGlobalRedzoneMagic: 865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr = "global-buffer-overflow"; 866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Decorator d; 870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.Warning()); 871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Report("ERROR: AddressSanitizer: %s on address " 872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n", 873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bug_descr, (void*)addr, pc, bp, sp); 874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s", d.EndWarning()); 875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org u32 curr_tid = GetCurrentTidOrInvalid(); 877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org char tname[128]; 878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Printf("%s%s of size %zu at %p thread T%d%s%s\n", 879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.Access(), 880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", 881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org access_size, (void*)addr, curr_tid, 882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)), 883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org d.EndAccess()); 884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org GET_STACK_TRACE_FATAL(pc, bp); 886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org stack.Print(); 887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress(addr, access_size); 889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReportErrorSummary(bug_descr, &stack); 890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PrintShadowMemoryForAddress(addr); 891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { 894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_report_callback = callback; 895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (callback) { 896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_message_buffer_size = 1 << 16; 897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_message_buffer = 898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (char*)MmapOrDie(error_message_buffer_size, __func__); 899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org error_message_buffer_pos = 0; 900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid __asan_describe_address(uptr addr) { 904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DescribeAddress(addr, 1); 905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgextern "C" { 908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgSANITIZER_INTERFACE_ATTRIBUTE 909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid __sanitizer_ptr_sub(void *a, void *b) { 910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CheckForInvalidPointerPair(a, b); 911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgSANITIZER_INTERFACE_ATTRIBUTE 913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid __sanitizer_ptr_cmp(void *a, void *b) { 914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CheckForInvalidPointerPair(a, b); 915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // extern "C" 917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !SANITIZER_SUPPORTS_WEAK_HOOKS 919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Provide default implementation of __asan_on_error that does nothing 920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// and may be overriden by user. 921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE 922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid __asan_on_error() {} 923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org