1*68d75effSDimitry Andric //===-- asan_errors.cpp -----------------------------------------*- C++ -*-===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 10*68d75effSDimitry Andric // 11*68d75effSDimitry Andric // ASan implementation for error structures. 12*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 13*68d75effSDimitry Andric 14*68d75effSDimitry Andric #include "asan_errors.h" 15*68d75effSDimitry Andric #include "asan_descriptions.h" 16*68d75effSDimitry Andric #include "asan_mapping.h" 17*68d75effSDimitry Andric #include "asan_report.h" 18*68d75effSDimitry Andric #include "asan_stack.h" 19*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 20*68d75effSDimitry Andric 21*68d75effSDimitry Andric namespace __asan { 22*68d75effSDimitry Andric 23*68d75effSDimitry Andric static void OnStackUnwind(const SignalContext &sig, 24*68d75effSDimitry Andric const void *callback_context, 25*68d75effSDimitry Andric BufferedStackTrace *stack) { 26*68d75effSDimitry Andric bool fast = common_flags()->fast_unwind_on_fatal; 27*68d75effSDimitry Andric #if SANITIZER_FREEBSD || SANITIZER_NETBSD 28*68d75effSDimitry Andric // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace() 29*68d75effSDimitry Andric // yields the call stack of the signal's handler and not of the code 30*68d75effSDimitry Andric // that raised the signal (as it does on Linux). 31*68d75effSDimitry Andric fast = true; 32*68d75effSDimitry Andric #endif 33*68d75effSDimitry Andric // Tests and maybe some users expect that scariness is going to be printed 34*68d75effSDimitry Andric // just before the stack. As only asan has scariness score we have no 35*68d75effSDimitry Andric // corresponding code in the sanitizer_common and we use this callback to 36*68d75effSDimitry Andric // print it. 37*68d75effSDimitry Andric static_cast<const ScarinessScoreBase *>(callback_context)->Print(); 38*68d75effSDimitry Andric stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 39*68d75effSDimitry Andric fast); 40*68d75effSDimitry Andric } 41*68d75effSDimitry Andric 42*68d75effSDimitry Andric void ErrorDeadlySignal::Print() { 43*68d75effSDimitry Andric ReportDeadlySignal(signal, tid, &OnStackUnwind, &scariness); 44*68d75effSDimitry Andric } 45*68d75effSDimitry Andric 46*68d75effSDimitry Andric void ErrorDoubleFree::Print() { 47*68d75effSDimitry Andric Decorator d; 48*68d75effSDimitry Andric Printf("%s", d.Error()); 49*68d75effSDimitry Andric Report( 50*68d75effSDimitry Andric "ERROR: AddressSanitizer: attempting %s on %p in thread %s:\n", 51*68d75effSDimitry Andric scariness.GetDescription(), addr_description.addr, 52*68d75effSDimitry Andric AsanThreadIdAndName(tid).c_str()); 53*68d75effSDimitry Andric Printf("%s", d.Default()); 54*68d75effSDimitry Andric scariness.Print(); 55*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(second_free_stack->trace[0], 56*68d75effSDimitry Andric second_free_stack->top_frame_bp); 57*68d75effSDimitry Andric stack.Print(); 58*68d75effSDimitry Andric addr_description.Print(); 59*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), &stack); 60*68d75effSDimitry Andric } 61*68d75effSDimitry Andric 62*68d75effSDimitry Andric void ErrorNewDeleteTypeMismatch::Print() { 63*68d75effSDimitry Andric Decorator d; 64*68d75effSDimitry Andric Printf("%s", d.Error()); 65*68d75effSDimitry Andric Report( 66*68d75effSDimitry Andric "ERROR: AddressSanitizer: %s on %p in thread %s:\n", 67*68d75effSDimitry Andric scariness.GetDescription(), addr_description.addr, 68*68d75effSDimitry Andric AsanThreadIdAndName(tid).c_str()); 69*68d75effSDimitry Andric Printf("%s object passed to delete has wrong type:\n", d.Default()); 70*68d75effSDimitry Andric if (delete_size != 0) { 71*68d75effSDimitry Andric Printf( 72*68d75effSDimitry Andric " size of the allocated type: %zd bytes;\n" 73*68d75effSDimitry Andric " size of the deallocated type: %zd bytes.\n", 74*68d75effSDimitry Andric addr_description.chunk_access.chunk_size, delete_size); 75*68d75effSDimitry Andric } 76*68d75effSDimitry Andric const uptr user_alignment = 77*68d75effSDimitry Andric addr_description.chunk_access.user_requested_alignment; 78*68d75effSDimitry Andric if (delete_alignment != user_alignment) { 79*68d75effSDimitry Andric char user_alignment_str[32]; 80*68d75effSDimitry Andric char delete_alignment_str[32]; 81*68d75effSDimitry Andric internal_snprintf(user_alignment_str, sizeof(user_alignment_str), 82*68d75effSDimitry Andric "%zd bytes", user_alignment); 83*68d75effSDimitry Andric internal_snprintf(delete_alignment_str, sizeof(delete_alignment_str), 84*68d75effSDimitry Andric "%zd bytes", delete_alignment); 85*68d75effSDimitry Andric static const char *kDefaultAlignment = "default-aligned"; 86*68d75effSDimitry Andric Printf( 87*68d75effSDimitry Andric " alignment of the allocated type: %s;\n" 88*68d75effSDimitry Andric " alignment of the deallocated type: %s.\n", 89*68d75effSDimitry Andric user_alignment > 0 ? user_alignment_str : kDefaultAlignment, 90*68d75effSDimitry Andric delete_alignment > 0 ? delete_alignment_str : kDefaultAlignment); 91*68d75effSDimitry Andric } 92*68d75effSDimitry Andric CHECK_GT(free_stack->size, 0); 93*68d75effSDimitry Andric scariness.Print(); 94*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 95*68d75effSDimitry Andric stack.Print(); 96*68d75effSDimitry Andric addr_description.Print(); 97*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), &stack); 98*68d75effSDimitry Andric Report( 99*68d75effSDimitry Andric "HINT: if you don't care about these errors you may set " 100*68d75effSDimitry Andric "ASAN_OPTIONS=new_delete_type_mismatch=0\n"); 101*68d75effSDimitry Andric } 102*68d75effSDimitry Andric 103*68d75effSDimitry Andric void ErrorFreeNotMalloced::Print() { 104*68d75effSDimitry Andric Decorator d; 105*68d75effSDimitry Andric Printf("%s", d.Error()); 106*68d75effSDimitry Andric Report( 107*68d75effSDimitry Andric "ERROR: AddressSanitizer: attempting free on address " 108*68d75effSDimitry Andric "which was not malloc()-ed: %p in thread %s\n", 109*68d75effSDimitry Andric addr_description.Address(), AsanThreadIdAndName(tid).c_str()); 110*68d75effSDimitry Andric Printf("%s", d.Default()); 111*68d75effSDimitry Andric CHECK_GT(free_stack->size, 0); 112*68d75effSDimitry Andric scariness.Print(); 113*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp); 114*68d75effSDimitry Andric stack.Print(); 115*68d75effSDimitry Andric addr_description.Print(); 116*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), &stack); 117*68d75effSDimitry Andric } 118*68d75effSDimitry Andric 119*68d75effSDimitry Andric void ErrorAllocTypeMismatch::Print() { 120*68d75effSDimitry Andric static const char *alloc_names[] = {"INVALID", "malloc", "operator new", 121*68d75effSDimitry Andric "operator new []"}; 122*68d75effSDimitry Andric static const char *dealloc_names[] = {"INVALID", "free", "operator delete", 123*68d75effSDimitry Andric "operator delete []"}; 124*68d75effSDimitry Andric CHECK_NE(alloc_type, dealloc_type); 125*68d75effSDimitry Andric Decorator d; 126*68d75effSDimitry Andric Printf("%s", d.Error()); 127*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n", 128*68d75effSDimitry Andric scariness.GetDescription(), alloc_names[alloc_type], 129*68d75effSDimitry Andric dealloc_names[dealloc_type], addr_description.Address()); 130*68d75effSDimitry Andric Printf("%s", d.Default()); 131*68d75effSDimitry Andric CHECK_GT(dealloc_stack->size, 0); 132*68d75effSDimitry Andric scariness.Print(); 133*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp); 134*68d75effSDimitry Andric stack.Print(); 135*68d75effSDimitry Andric addr_description.Print(); 136*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), &stack); 137*68d75effSDimitry Andric Report( 138*68d75effSDimitry Andric "HINT: if you don't care about these errors you may set " 139*68d75effSDimitry Andric "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); 140*68d75effSDimitry Andric } 141*68d75effSDimitry Andric 142*68d75effSDimitry Andric void ErrorMallocUsableSizeNotOwned::Print() { 143*68d75effSDimitry Andric Decorator d; 144*68d75effSDimitry Andric Printf("%s", d.Error()); 145*68d75effSDimitry Andric Report( 146*68d75effSDimitry Andric "ERROR: AddressSanitizer: attempting to call malloc_usable_size() for " 147*68d75effSDimitry Andric "pointer which is not owned: %p\n", 148*68d75effSDimitry Andric addr_description.Address()); 149*68d75effSDimitry Andric Printf("%s", d.Default()); 150*68d75effSDimitry Andric stack->Print(); 151*68d75effSDimitry Andric addr_description.Print(); 152*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 153*68d75effSDimitry Andric } 154*68d75effSDimitry Andric 155*68d75effSDimitry Andric void ErrorSanitizerGetAllocatedSizeNotOwned::Print() { 156*68d75effSDimitry Andric Decorator d; 157*68d75effSDimitry Andric Printf("%s", d.Error()); 158*68d75effSDimitry Andric Report( 159*68d75effSDimitry Andric "ERROR: AddressSanitizer: attempting to call " 160*68d75effSDimitry Andric "__sanitizer_get_allocated_size() for pointer which is not owned: %p\n", 161*68d75effSDimitry Andric addr_description.Address()); 162*68d75effSDimitry Andric Printf("%s", d.Default()); 163*68d75effSDimitry Andric stack->Print(); 164*68d75effSDimitry Andric addr_description.Print(); 165*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 166*68d75effSDimitry Andric } 167*68d75effSDimitry Andric 168*68d75effSDimitry Andric void ErrorCallocOverflow::Print() { 169*68d75effSDimitry Andric Decorator d; 170*68d75effSDimitry Andric Printf("%s", d.Error()); 171*68d75effSDimitry Andric Report( 172*68d75effSDimitry Andric "ERROR: AddressSanitizer: calloc parameters overflow: count * size " 173*68d75effSDimitry Andric "(%zd * %zd) cannot be represented in type size_t (thread %s)\n", 174*68d75effSDimitry Andric count, size, AsanThreadIdAndName(tid).c_str()); 175*68d75effSDimitry Andric Printf("%s", d.Default()); 176*68d75effSDimitry Andric stack->Print(); 177*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 178*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 179*68d75effSDimitry Andric } 180*68d75effSDimitry Andric 181*68d75effSDimitry Andric void ErrorReallocArrayOverflow::Print() { 182*68d75effSDimitry Andric Decorator d; 183*68d75effSDimitry Andric Printf("%s", d.Error()); 184*68d75effSDimitry Andric Report( 185*68d75effSDimitry Andric "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size " 186*68d75effSDimitry Andric "(%zd * %zd) cannot be represented in type size_t (thread %s)\n", 187*68d75effSDimitry Andric count, size, AsanThreadIdAndName(tid).c_str()); 188*68d75effSDimitry Andric Printf("%s", d.Default()); 189*68d75effSDimitry Andric stack->Print(); 190*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 191*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 192*68d75effSDimitry Andric } 193*68d75effSDimitry Andric 194*68d75effSDimitry Andric void ErrorPvallocOverflow::Print() { 195*68d75effSDimitry Andric Decorator d; 196*68d75effSDimitry Andric Printf("%s", d.Error()); 197*68d75effSDimitry Andric Report( 198*68d75effSDimitry Andric "ERROR: AddressSanitizer: pvalloc parameters overflow: size 0x%zx " 199*68d75effSDimitry Andric "rounded up to system page size 0x%zx cannot be represented in type " 200*68d75effSDimitry Andric "size_t (thread %s)\n", 201*68d75effSDimitry Andric size, GetPageSizeCached(), AsanThreadIdAndName(tid).c_str()); 202*68d75effSDimitry Andric Printf("%s", d.Default()); 203*68d75effSDimitry Andric stack->Print(); 204*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 205*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 206*68d75effSDimitry Andric } 207*68d75effSDimitry Andric 208*68d75effSDimitry Andric void ErrorInvalidAllocationAlignment::Print() { 209*68d75effSDimitry Andric Decorator d; 210*68d75effSDimitry Andric Printf("%s", d.Error()); 211*68d75effSDimitry Andric Report( 212*68d75effSDimitry Andric "ERROR: AddressSanitizer: invalid allocation alignment: %zd, " 213*68d75effSDimitry Andric "alignment must be a power of two (thread %s)\n", 214*68d75effSDimitry Andric alignment, AsanThreadIdAndName(tid).c_str()); 215*68d75effSDimitry Andric Printf("%s", d.Default()); 216*68d75effSDimitry Andric stack->Print(); 217*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 218*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 219*68d75effSDimitry Andric } 220*68d75effSDimitry Andric 221*68d75effSDimitry Andric void ErrorInvalidAlignedAllocAlignment::Print() { 222*68d75effSDimitry Andric Decorator d; 223*68d75effSDimitry Andric Printf("%s", d.Error()); 224*68d75effSDimitry Andric #if SANITIZER_POSIX 225*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: invalid alignment requested in " 226*68d75effSDimitry Andric "aligned_alloc: %zd, alignment must be a power of two and the " 227*68d75effSDimitry Andric "requested size 0x%zx must be a multiple of alignment " 228*68d75effSDimitry Andric "(thread %s)\n", alignment, size, AsanThreadIdAndName(tid).c_str()); 229*68d75effSDimitry Andric #else 230*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: invalid alignment requested in " 231*68d75effSDimitry Andric "aligned_alloc: %zd, the requested size 0x%zx must be a multiple of " 232*68d75effSDimitry Andric "alignment (thread %s)\n", alignment, size, 233*68d75effSDimitry Andric AsanThreadIdAndName(tid).c_str()); 234*68d75effSDimitry Andric #endif 235*68d75effSDimitry Andric Printf("%s", d.Default()); 236*68d75effSDimitry Andric stack->Print(); 237*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 238*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 239*68d75effSDimitry Andric } 240*68d75effSDimitry Andric 241*68d75effSDimitry Andric void ErrorInvalidPosixMemalignAlignment::Print() { 242*68d75effSDimitry Andric Decorator d; 243*68d75effSDimitry Andric Printf("%s", d.Error()); 244*68d75effSDimitry Andric Report( 245*68d75effSDimitry Andric "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: " 246*68d75effSDimitry Andric "%zd, alignment must be a power of two and a multiple of sizeof(void*) " 247*68d75effSDimitry Andric "== %zd (thread %s)\n", 248*68d75effSDimitry Andric alignment, sizeof(void *), AsanThreadIdAndName(tid).c_str()); 249*68d75effSDimitry Andric Printf("%s", d.Default()); 250*68d75effSDimitry Andric stack->Print(); 251*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 252*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 253*68d75effSDimitry Andric } 254*68d75effSDimitry Andric 255*68d75effSDimitry Andric void ErrorAllocationSizeTooBig::Print() { 256*68d75effSDimitry Andric Decorator d; 257*68d75effSDimitry Andric Printf("%s", d.Error()); 258*68d75effSDimitry Andric Report( 259*68d75effSDimitry Andric "ERROR: AddressSanitizer: requested allocation size 0x%zx (0x%zx after " 260*68d75effSDimitry Andric "adjustments for alignment, red zones etc.) exceeds maximum supported " 261*68d75effSDimitry Andric "size of 0x%zx (thread %s)\n", 262*68d75effSDimitry Andric user_size, total_size, max_size, AsanThreadIdAndName(tid).c_str()); 263*68d75effSDimitry Andric Printf("%s", d.Default()); 264*68d75effSDimitry Andric stack->Print(); 265*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 266*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 267*68d75effSDimitry Andric } 268*68d75effSDimitry Andric 269*68d75effSDimitry Andric void ErrorRssLimitExceeded::Print() { 270*68d75effSDimitry Andric Decorator d; 271*68d75effSDimitry Andric Printf("%s", d.Error()); 272*68d75effSDimitry Andric Report( 273*68d75effSDimitry Andric "ERROR: AddressSanitizer: specified RSS limit exceeded, currently set to " 274*68d75effSDimitry Andric "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb); 275*68d75effSDimitry Andric Printf("%s", d.Default()); 276*68d75effSDimitry Andric stack->Print(); 277*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 278*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 279*68d75effSDimitry Andric } 280*68d75effSDimitry Andric 281*68d75effSDimitry Andric void ErrorOutOfMemory::Print() { 282*68d75effSDimitry Andric Decorator d; 283*68d75effSDimitry Andric Printf("%s", d.Error()); 284*68d75effSDimitry Andric Report( 285*68d75effSDimitry Andric "ERROR: AddressSanitizer: allocator is out of memory trying to allocate " 286*68d75effSDimitry Andric "0x%zx bytes\n", requested_size); 287*68d75effSDimitry Andric Printf("%s", d.Default()); 288*68d75effSDimitry Andric stack->Print(); 289*68d75effSDimitry Andric PrintHintAllocatorCannotReturnNull(); 290*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 291*68d75effSDimitry Andric } 292*68d75effSDimitry Andric 293*68d75effSDimitry Andric void ErrorStringFunctionMemoryRangesOverlap::Print() { 294*68d75effSDimitry Andric Decorator d; 295*68d75effSDimitry Andric char bug_type[100]; 296*68d75effSDimitry Andric internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); 297*68d75effSDimitry Andric Printf("%s", d.Error()); 298*68d75effSDimitry Andric Report( 299*68d75effSDimitry Andric "ERROR: AddressSanitizer: %s: memory ranges [%p,%p) and [%p, %p) " 300*68d75effSDimitry Andric "overlap\n", 301*68d75effSDimitry Andric bug_type, addr1_description.Address(), 302*68d75effSDimitry Andric addr1_description.Address() + length1, addr2_description.Address(), 303*68d75effSDimitry Andric addr2_description.Address() + length2); 304*68d75effSDimitry Andric Printf("%s", d.Default()); 305*68d75effSDimitry Andric scariness.Print(); 306*68d75effSDimitry Andric stack->Print(); 307*68d75effSDimitry Andric addr1_description.Print(); 308*68d75effSDimitry Andric addr2_description.Print(); 309*68d75effSDimitry Andric ReportErrorSummary(bug_type, stack); 310*68d75effSDimitry Andric } 311*68d75effSDimitry Andric 312*68d75effSDimitry Andric void ErrorStringFunctionSizeOverflow::Print() { 313*68d75effSDimitry Andric Decorator d; 314*68d75effSDimitry Andric Printf("%s", d.Error()); 315*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", 316*68d75effSDimitry Andric scariness.GetDescription(), size); 317*68d75effSDimitry Andric Printf("%s", d.Default()); 318*68d75effSDimitry Andric scariness.Print(); 319*68d75effSDimitry Andric stack->Print(); 320*68d75effSDimitry Andric addr_description.Print(); 321*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 322*68d75effSDimitry Andric } 323*68d75effSDimitry Andric 324*68d75effSDimitry Andric void ErrorBadParamsToAnnotateContiguousContainer::Print() { 325*68d75effSDimitry Andric Report( 326*68d75effSDimitry Andric "ERROR: AddressSanitizer: bad parameters to " 327*68d75effSDimitry Andric "__sanitizer_annotate_contiguous_container:\n" 328*68d75effSDimitry Andric " beg : %p\n" 329*68d75effSDimitry Andric " end : %p\n" 330*68d75effSDimitry Andric " old_mid : %p\n" 331*68d75effSDimitry Andric " new_mid : %p\n", 332*68d75effSDimitry Andric beg, end, old_mid, new_mid); 333*68d75effSDimitry Andric uptr granularity = SHADOW_GRANULARITY; 334*68d75effSDimitry Andric if (!IsAligned(beg, granularity)) 335*68d75effSDimitry Andric Report("ERROR: beg is not aligned by %d\n", granularity); 336*68d75effSDimitry Andric stack->Print(); 337*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), stack); 338*68d75effSDimitry Andric } 339*68d75effSDimitry Andric 340*68d75effSDimitry Andric void ErrorODRViolation::Print() { 341*68d75effSDimitry Andric Decorator d; 342*68d75effSDimitry Andric Printf("%s", d.Error()); 343*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(), 344*68d75effSDimitry Andric global1.beg); 345*68d75effSDimitry Andric Printf("%s", d.Default()); 346*68d75effSDimitry Andric InternalScopedString g1_loc(256), g2_loc(256); 347*68d75effSDimitry Andric PrintGlobalLocation(&g1_loc, global1); 348*68d75effSDimitry Andric PrintGlobalLocation(&g2_loc, global2); 349*68d75effSDimitry Andric Printf(" [1] size=%zd '%s' %s\n", global1.size, 350*68d75effSDimitry Andric MaybeDemangleGlobalName(global1.name), g1_loc.data()); 351*68d75effSDimitry Andric Printf(" [2] size=%zd '%s' %s\n", global2.size, 352*68d75effSDimitry Andric MaybeDemangleGlobalName(global2.name), g2_loc.data()); 353*68d75effSDimitry Andric if (stack_id1 && stack_id2) { 354*68d75effSDimitry Andric Printf("These globals were registered at these points:\n"); 355*68d75effSDimitry Andric Printf(" [1]:\n"); 356*68d75effSDimitry Andric StackDepotGet(stack_id1).Print(); 357*68d75effSDimitry Andric Printf(" [2]:\n"); 358*68d75effSDimitry Andric StackDepotGet(stack_id2).Print(); 359*68d75effSDimitry Andric } 360*68d75effSDimitry Andric Report( 361*68d75effSDimitry Andric "HINT: if you don't care about these errors you may set " 362*68d75effSDimitry Andric "ASAN_OPTIONS=detect_odr_violation=0\n"); 363*68d75effSDimitry Andric InternalScopedString error_msg(256); 364*68d75effSDimitry Andric error_msg.append("%s: global '%s' at %s", scariness.GetDescription(), 365*68d75effSDimitry Andric MaybeDemangleGlobalName(global1.name), g1_loc.data()); 366*68d75effSDimitry Andric ReportErrorSummary(error_msg.data()); 367*68d75effSDimitry Andric } 368*68d75effSDimitry Andric 369*68d75effSDimitry Andric void ErrorInvalidPointerPair::Print() { 370*68d75effSDimitry Andric Decorator d; 371*68d75effSDimitry Andric Printf("%s", d.Error()); 372*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(), 373*68d75effSDimitry Andric addr1_description.Address(), addr2_description.Address()); 374*68d75effSDimitry Andric Printf("%s", d.Default()); 375*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(pc, bp); 376*68d75effSDimitry Andric stack.Print(); 377*68d75effSDimitry Andric addr1_description.Print(); 378*68d75effSDimitry Andric addr2_description.Print(); 379*68d75effSDimitry Andric ReportErrorSummary(scariness.GetDescription(), &stack); 380*68d75effSDimitry Andric } 381*68d75effSDimitry Andric 382*68d75effSDimitry Andric static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) { 383*68d75effSDimitry Andric return s[-1] > 127 && s[1] > 127; 384*68d75effSDimitry Andric } 385*68d75effSDimitry Andric 386*68d75effSDimitry Andric ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr, 387*68d75effSDimitry Andric bool is_write_, uptr access_size_) 388*68d75effSDimitry Andric : ErrorBase(tid), 389*68d75effSDimitry Andric addr_description(addr, access_size_, /*shouldLockThreadRegistry=*/false), 390*68d75effSDimitry Andric pc(pc_), 391*68d75effSDimitry Andric bp(bp_), 392*68d75effSDimitry Andric sp(sp_), 393*68d75effSDimitry Andric access_size(access_size_), 394*68d75effSDimitry Andric is_write(is_write_), 395*68d75effSDimitry Andric shadow_val(0) { 396*68d75effSDimitry Andric scariness.Clear(); 397*68d75effSDimitry Andric if (access_size) { 398*68d75effSDimitry Andric if (access_size <= 9) { 399*68d75effSDimitry Andric char desr[] = "?-byte"; 400*68d75effSDimitry Andric desr[0] = '0' + access_size; 401*68d75effSDimitry Andric scariness.Scare(access_size + access_size / 2, desr); 402*68d75effSDimitry Andric } else if (access_size >= 10) { 403*68d75effSDimitry Andric scariness.Scare(15, "multi-byte"); 404*68d75effSDimitry Andric } 405*68d75effSDimitry Andric is_write ? scariness.Scare(20, "write") : scariness.Scare(1, "read"); 406*68d75effSDimitry Andric 407*68d75effSDimitry Andric // Determine the error type. 408*68d75effSDimitry Andric bug_descr = "unknown-crash"; 409*68d75effSDimitry Andric if (AddrIsInMem(addr)) { 410*68d75effSDimitry Andric u8 *shadow_addr = (u8 *)MemToShadow(addr); 411*68d75effSDimitry Andric // If we are accessing 16 bytes, look at the second shadow byte. 412*68d75effSDimitry Andric if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++; 413*68d75effSDimitry Andric // If we are in the partial right redzone, look at the next shadow byte. 414*68d75effSDimitry Andric if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++; 415*68d75effSDimitry Andric bool far_from_bounds = false; 416*68d75effSDimitry Andric shadow_val = *shadow_addr; 417*68d75effSDimitry Andric int bug_type_score = 0; 418*68d75effSDimitry Andric // For use-after-frees reads are almost as bad as writes. 419*68d75effSDimitry Andric int read_after_free_bonus = 0; 420*68d75effSDimitry Andric switch (shadow_val) { 421*68d75effSDimitry Andric case kAsanHeapLeftRedzoneMagic: 422*68d75effSDimitry Andric case kAsanArrayCookieMagic: 423*68d75effSDimitry Andric bug_descr = "heap-buffer-overflow"; 424*68d75effSDimitry Andric bug_type_score = 10; 425*68d75effSDimitry Andric far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 426*68d75effSDimitry Andric break; 427*68d75effSDimitry Andric case kAsanHeapFreeMagic: 428*68d75effSDimitry Andric bug_descr = "heap-use-after-free"; 429*68d75effSDimitry Andric bug_type_score = 20; 430*68d75effSDimitry Andric if (!is_write) read_after_free_bonus = 18; 431*68d75effSDimitry Andric break; 432*68d75effSDimitry Andric case kAsanStackLeftRedzoneMagic: 433*68d75effSDimitry Andric bug_descr = "stack-buffer-underflow"; 434*68d75effSDimitry Andric bug_type_score = 25; 435*68d75effSDimitry Andric far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 436*68d75effSDimitry Andric break; 437*68d75effSDimitry Andric case kAsanInitializationOrderMagic: 438*68d75effSDimitry Andric bug_descr = "initialization-order-fiasco"; 439*68d75effSDimitry Andric bug_type_score = 1; 440*68d75effSDimitry Andric break; 441*68d75effSDimitry Andric case kAsanStackMidRedzoneMagic: 442*68d75effSDimitry Andric case kAsanStackRightRedzoneMagic: 443*68d75effSDimitry Andric bug_descr = "stack-buffer-overflow"; 444*68d75effSDimitry Andric bug_type_score = 25; 445*68d75effSDimitry Andric far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 446*68d75effSDimitry Andric break; 447*68d75effSDimitry Andric case kAsanStackAfterReturnMagic: 448*68d75effSDimitry Andric bug_descr = "stack-use-after-return"; 449*68d75effSDimitry Andric bug_type_score = 30; 450*68d75effSDimitry Andric if (!is_write) read_after_free_bonus = 18; 451*68d75effSDimitry Andric break; 452*68d75effSDimitry Andric case kAsanUserPoisonedMemoryMagic: 453*68d75effSDimitry Andric bug_descr = "use-after-poison"; 454*68d75effSDimitry Andric bug_type_score = 20; 455*68d75effSDimitry Andric break; 456*68d75effSDimitry Andric case kAsanContiguousContainerOOBMagic: 457*68d75effSDimitry Andric bug_descr = "container-overflow"; 458*68d75effSDimitry Andric bug_type_score = 10; 459*68d75effSDimitry Andric break; 460*68d75effSDimitry Andric case kAsanStackUseAfterScopeMagic: 461*68d75effSDimitry Andric bug_descr = "stack-use-after-scope"; 462*68d75effSDimitry Andric bug_type_score = 10; 463*68d75effSDimitry Andric break; 464*68d75effSDimitry Andric case kAsanGlobalRedzoneMagic: 465*68d75effSDimitry Andric bug_descr = "global-buffer-overflow"; 466*68d75effSDimitry Andric bug_type_score = 10; 467*68d75effSDimitry Andric far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 468*68d75effSDimitry Andric break; 469*68d75effSDimitry Andric case kAsanIntraObjectRedzone: 470*68d75effSDimitry Andric bug_descr = "intra-object-overflow"; 471*68d75effSDimitry Andric bug_type_score = 10; 472*68d75effSDimitry Andric break; 473*68d75effSDimitry Andric case kAsanAllocaLeftMagic: 474*68d75effSDimitry Andric case kAsanAllocaRightMagic: 475*68d75effSDimitry Andric bug_descr = "dynamic-stack-buffer-overflow"; 476*68d75effSDimitry Andric bug_type_score = 25; 477*68d75effSDimitry Andric far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr); 478*68d75effSDimitry Andric break; 479*68d75effSDimitry Andric } 480*68d75effSDimitry Andric scariness.Scare(bug_type_score + read_after_free_bonus, bug_descr); 481*68d75effSDimitry Andric if (far_from_bounds) scariness.Scare(10, "far-from-bounds"); 482*68d75effSDimitry Andric } 483*68d75effSDimitry Andric } 484*68d75effSDimitry Andric } 485*68d75effSDimitry Andric 486*68d75effSDimitry Andric static void PrintContainerOverflowHint() { 487*68d75effSDimitry Andric Printf("HINT: if you don't care about these errors you may set " 488*68d75effSDimitry Andric "ASAN_OPTIONS=detect_container_overflow=0.\n" 489*68d75effSDimitry Andric "If you suspect a false positive see also: " 490*68d75effSDimitry Andric "https://github.com/google/sanitizers/wiki/" 491*68d75effSDimitry Andric "AddressSanitizerContainerOverflow.\n"); 492*68d75effSDimitry Andric } 493*68d75effSDimitry Andric 494*68d75effSDimitry Andric static void PrintShadowByte(InternalScopedString *str, const char *before, 495*68d75effSDimitry Andric u8 byte, const char *after = "\n") { 496*68d75effSDimitry Andric PrintMemoryByte(str, before, byte, /*in_shadow*/true, after); 497*68d75effSDimitry Andric } 498*68d75effSDimitry Andric 499*68d75effSDimitry Andric static void PrintLegend(InternalScopedString *str) { 500*68d75effSDimitry Andric str->append( 501*68d75effSDimitry Andric "Shadow byte legend (one shadow byte represents %d " 502*68d75effSDimitry Andric "application bytes):\n", 503*68d75effSDimitry Andric (int)SHADOW_GRANULARITY); 504*68d75effSDimitry Andric PrintShadowByte(str, " Addressable: ", 0); 505*68d75effSDimitry Andric str->append(" Partially addressable: "); 506*68d75effSDimitry Andric for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); 507*68d75effSDimitry Andric str->append("\n"); 508*68d75effSDimitry Andric PrintShadowByte(str, " Heap left redzone: ", 509*68d75effSDimitry Andric kAsanHeapLeftRedzoneMagic); 510*68d75effSDimitry Andric PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic); 511*68d75effSDimitry Andric PrintShadowByte(str, " Stack left redzone: ", 512*68d75effSDimitry Andric kAsanStackLeftRedzoneMagic); 513*68d75effSDimitry Andric PrintShadowByte(str, " Stack mid redzone: ", 514*68d75effSDimitry Andric kAsanStackMidRedzoneMagic); 515*68d75effSDimitry Andric PrintShadowByte(str, " Stack right redzone: ", 516*68d75effSDimitry Andric kAsanStackRightRedzoneMagic); 517*68d75effSDimitry Andric PrintShadowByte(str, " Stack after return: ", 518*68d75effSDimitry Andric kAsanStackAfterReturnMagic); 519*68d75effSDimitry Andric PrintShadowByte(str, " Stack use after scope: ", 520*68d75effSDimitry Andric kAsanStackUseAfterScopeMagic); 521*68d75effSDimitry Andric PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic); 522*68d75effSDimitry Andric PrintShadowByte(str, " Global init order: ", 523*68d75effSDimitry Andric kAsanInitializationOrderMagic); 524*68d75effSDimitry Andric PrintShadowByte(str, " Poisoned by user: ", 525*68d75effSDimitry Andric kAsanUserPoisonedMemoryMagic); 526*68d75effSDimitry Andric PrintShadowByte(str, " Container overflow: ", 527*68d75effSDimitry Andric kAsanContiguousContainerOOBMagic); 528*68d75effSDimitry Andric PrintShadowByte(str, " Array cookie: ", 529*68d75effSDimitry Andric kAsanArrayCookieMagic); 530*68d75effSDimitry Andric PrintShadowByte(str, " Intra object redzone: ", 531*68d75effSDimitry Andric kAsanIntraObjectRedzone); 532*68d75effSDimitry Andric PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); 533*68d75effSDimitry Andric PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic); 534*68d75effSDimitry Andric PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); 535*68d75effSDimitry Andric PrintShadowByte(str, " Shadow gap: ", kAsanShadowGap); 536*68d75effSDimitry Andric } 537*68d75effSDimitry Andric 538*68d75effSDimitry Andric static void PrintShadowBytes(InternalScopedString *str, const char *before, 539*68d75effSDimitry Andric u8 *bytes, u8 *guilty, uptr n) { 540*68d75effSDimitry Andric Decorator d; 541*68d75effSDimitry Andric if (before) str->append("%s%p:", before, bytes); 542*68d75effSDimitry Andric for (uptr i = 0; i < n; i++) { 543*68d75effSDimitry Andric u8 *p = bytes + i; 544*68d75effSDimitry Andric const char *before = 545*68d75effSDimitry Andric p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " "; 546*68d75effSDimitry Andric const char *after = p == guilty ? "]" : ""; 547*68d75effSDimitry Andric PrintShadowByte(str, before, *p, after); 548*68d75effSDimitry Andric } 549*68d75effSDimitry Andric str->append("\n"); 550*68d75effSDimitry Andric } 551*68d75effSDimitry Andric 552*68d75effSDimitry Andric static void PrintShadowMemoryForAddress(uptr addr) { 553*68d75effSDimitry Andric if (!AddrIsInMem(addr)) return; 554*68d75effSDimitry Andric uptr shadow_addr = MemToShadow(addr); 555*68d75effSDimitry Andric const uptr n_bytes_per_row = 16; 556*68d75effSDimitry Andric uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1); 557*68d75effSDimitry Andric InternalScopedString str(4096 * 8); 558*68d75effSDimitry Andric str.append("Shadow bytes around the buggy address:\n"); 559*68d75effSDimitry Andric for (int i = -5; i <= 5; i++) { 560*68d75effSDimitry Andric uptr row_shadow_addr = aligned_shadow + i * n_bytes_per_row; 561*68d75effSDimitry Andric // Skip rows that would be outside the shadow range. This can happen when 562*68d75effSDimitry Andric // the user address is near the bottom, top, or shadow gap of the address 563*68d75effSDimitry Andric // space. 564*68d75effSDimitry Andric if (!AddrIsInShadow(row_shadow_addr)) continue; 565*68d75effSDimitry Andric const char *prefix = (i == 0) ? "=>" : " "; 566*68d75effSDimitry Andric PrintShadowBytes(&str, prefix, (u8 *)row_shadow_addr, (u8 *)shadow_addr, 567*68d75effSDimitry Andric n_bytes_per_row); 568*68d75effSDimitry Andric } 569*68d75effSDimitry Andric if (flags()->print_legend) PrintLegend(&str); 570*68d75effSDimitry Andric Printf("%s", str.data()); 571*68d75effSDimitry Andric } 572*68d75effSDimitry Andric 573*68d75effSDimitry Andric void ErrorGeneric::Print() { 574*68d75effSDimitry Andric Decorator d; 575*68d75effSDimitry Andric Printf("%s", d.Error()); 576*68d75effSDimitry Andric uptr addr = addr_description.Address(); 577*68d75effSDimitry Andric Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n", 578*68d75effSDimitry Andric bug_descr, (void *)addr, pc, bp, sp); 579*68d75effSDimitry Andric Printf("%s", d.Default()); 580*68d75effSDimitry Andric 581*68d75effSDimitry Andric Printf("%s%s of size %zu at %p thread %s%s\n", d.Access(), 582*68d75effSDimitry Andric access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", access_size, 583*68d75effSDimitry Andric (void *)addr, AsanThreadIdAndName(tid).c_str(), d.Default()); 584*68d75effSDimitry Andric 585*68d75effSDimitry Andric scariness.Print(); 586*68d75effSDimitry Andric GET_STACK_TRACE_FATAL(pc, bp); 587*68d75effSDimitry Andric stack.Print(); 588*68d75effSDimitry Andric 589*68d75effSDimitry Andric // Pass bug_descr because we have a special case for 590*68d75effSDimitry Andric // initialization-order-fiasco 591*68d75effSDimitry Andric addr_description.Print(bug_descr); 592*68d75effSDimitry Andric if (shadow_val == kAsanContiguousContainerOOBMagic) 593*68d75effSDimitry Andric PrintContainerOverflowHint(); 594*68d75effSDimitry Andric ReportErrorSummary(bug_descr, &stack); 595*68d75effSDimitry Andric PrintShadowMemoryForAddress(addr); 596*68d75effSDimitry Andric } 597*68d75effSDimitry Andric 598*68d75effSDimitry Andric } // namespace __asan 599