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