1 //===-- msan_report.cc ----------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of MemorySanitizer.
11 //
12 // Error reporting.
13 //===----------------------------------------------------------------------===//
14
15 #include "msan.h"
16 #include "sanitizer_common/sanitizer_allocator_internal.h"
17 #include "sanitizer_common/sanitizer_common.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_mutex.h"
20 #include "sanitizer_common/sanitizer_report_decorator.h"
21 #include "sanitizer_common/sanitizer_stackdepot.h"
22 #include "sanitizer_common/sanitizer_symbolizer.h"
23
24 using namespace __sanitizer;
25
26 namespace __msan {
27
PrintsToTtyCached()28 static bool PrintsToTtyCached() {
29 static int cached = 0;
30 static bool prints_to_tty;
31 if (!cached) { // Ok wrt threads since we are printing only from one thread.
32 prints_to_tty = PrintsToTty();
33 cached = 1;
34 }
35 return prints_to_tty;
36 }
37
38 class Decorator: private __sanitizer::AnsiColorDecorator {
39 public:
Decorator()40 Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
Warning()41 const char *Warning() { return Red(); }
Origin()42 const char *Origin() { return Magenta(); }
Name()43 const char *Name() { return Green(); }
End()44 const char *End() { return Default(); }
45 };
46
PrintStack(const uptr * trace,uptr size)47 static void PrintStack(const uptr *trace, uptr size) {
48 SymbolizerScope sym_scope;
49 StackTrace::PrintStack(trace, size, true,
50 common_flags()->strip_path_prefix, 0);
51 }
52
DescribeOrigin(u32 origin)53 static void DescribeOrigin(u32 origin) {
54 Decorator d;
55 if (flags()->verbosity)
56 Printf(" raw origin id: %d\n", origin);
57 if (const char *so = __msan_get_origin_descr_if_stack(origin)) {
58 char* s = internal_strdup(so);
59 char* sep = internal_strchr(s, '@');
60 CHECK(sep);
61 *sep = '\0';
62 Printf("%s", d.Origin());
63 Printf(" %sUninitialized value was created by an allocation of '%s%s%s'"
64 " in the stack frame of function '%s%s%s'%s\n",
65 d.Origin(), d.Name(), s, d.Origin(), d.Name(), Demangle(sep + 1),
66 d.Origin(), d.End());
67 InternalFree(s);
68 } else {
69 uptr size = 0;
70 const uptr *trace = StackDepotGet(origin, &size);
71 Printf(" %sUninitialized value was created by a heap allocation%s\n",
72 d.Origin(), d.End());
73 PrintStack(trace, size);
74 }
75 }
76
ReportSummary(const char * error_type,StackTrace * stack)77 static void ReportSummary(const char *error_type, StackTrace *stack) {
78 if (!stack->size || !IsSymbolizerAvailable()) return;
79 AddressInfo ai;
80 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
81 {
82 SymbolizerScope sym_scope;
83 SymbolizeCode(pc, &ai, 1);
84 }
85 ReportErrorSummary(error_type,
86 StripPathPrefix(ai.file,
87 common_flags()->strip_path_prefix),
88 ai.line, ai.function);
89 }
90
ReportUMR(StackTrace * stack,u32 origin)91 void ReportUMR(StackTrace *stack, u32 origin) {
92 if (!__msan::flags()->report_umrs) return;
93
94 SpinMutexLock l(&CommonSanitizerReportMutex);
95
96 Decorator d;
97 Printf("%s", d.Warning());
98 Report(" WARNING: MemorySanitizer: use-of-uninitialized-value\n");
99 Printf("%s", d.End());
100 PrintStack(stack->trace, stack->size);
101 if (origin) {
102 DescribeOrigin(origin);
103 }
104 ReportSummary("use-of-uninitialized-value", stack);
105 }
106
ReportExpectedUMRNotFound(StackTrace * stack)107 void ReportExpectedUMRNotFound(StackTrace *stack) {
108 SpinMutexLock l(&CommonSanitizerReportMutex);
109
110 Printf(" WARNING: Expected use of uninitialized value not found\n");
111 PrintStack(stack->trace, stack->size);
112 }
113
ReportAtExitStatistics()114 void ReportAtExitStatistics() {
115 SpinMutexLock l(&CommonSanitizerReportMutex);
116
117 Decorator d;
118 Printf("%s", d.Warning());
119 Printf("MemorySanitizer: %d warnings reported.\n", msan_report_count);
120 Printf("%s", d.End());
121 }
122
123
124 } // namespace __msan
125