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