Home | History | Annotate | Download | only in msan
      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 
     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:
     40   Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
     41   const char *Warning()    { return Red(); }
     42   const char *Origin()     { return Magenta(); }
     43   const char *Name()   { return Green(); }
     44   const char *End()    { return Default(); }
     45 };
     46 
     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 
     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 
     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 
     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 
    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 
    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