Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -44,20 +44,6 @@ } // ---------------------- Decorator ------------------------------ {{{1 -bool PrintsToTtyCached() { - // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color - // printing on Windows. - if (SANITIZER_WINDOWS) - return 0; - - static int cached = 0; - static bool prints_to_tty; - if (!cached) { // Ok wrt threads since we are printing only from one thread. - prints_to_tty = PrintsToTty(); - cached = 1; - } - return prints_to_tty; -} class Decorator: private __sanitizer::AnsiColorDecorator { public: Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { } Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -21,6 +21,7 @@ #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_stoptheworld.h" #include "sanitizer_common/sanitizer_suppressions.h" +#include "sanitizer_common/sanitizer_report_decorator.h" #if CAN_SANITIZE_LEAKS namespace __lsan { @@ -96,6 +97,14 @@ InitializePlatformSpecificModules(); } +class Decorator: private __sanitizer::AnsiColorDecorator { + public: + Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { } + const char *Error() { return Red(); } + const char *Leak() { return Blue(); } + const char *End() { return Default(); } +}; + static inline bool CanBeAHeapPointer(uptr p) { // Since our heap is located in mmap-ed memory, we can assume a sensible lower // bound on heap addresses. @@ -372,10 +381,13 @@ } uptr have_unsuppressed = param.leak_report.ApplySuppressions(); if (have_unsuppressed) { + Decorator d; Printf("\n" "=================================================================" "\n"); + Printf("%s", d.Error()); Report("ERROR: LeakSanitizer: detected memory leaks\n"); + Printf("%s", d.End()); param.leak_report.PrintLargest(flags()->max_leaks); } if (have_unsuppressed || (flags()->verbosity >= 1)) { @@ -460,11 +472,14 @@ Printf("The %zu largest leak(s):\n", num_leaks_to_print); InternalSort(&leaks_, leaks_.size(), LeakComparator); uptr leaks_printed = 0; + Decorator d; for (uptr i = 0; i < leaks_.size(); i++) { if (leaks_[i].is_suppressed) continue; + Printf("%s", d.Leak()); Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n", leaks_[i].is_directly_leaked ? "Direct" : "Indirect", leaks_[i].total_size, leaks_[i].hit_count); + Printf("%s", d.End()); PrintStackTraceById(leaks_[i].stack_trace_id); Printf("\n"); leaks_printed++; Index: lib/msan/msan_report.cc =================================================================== --- lib/msan/msan_report.cc +++ lib/msan/msan_report.cc @@ -25,16 +25,6 @@ namespace __msan { -static bool PrintsToTtyCached() { - static int cached = 0; - static bool prints_to_tty; - if (!cached) { // Ok wrt threads since we are printing only from one thread. - prints_to_tty = PrintsToTty(); - cached = 1; - } - return prints_to_tty; -} - class Decorator: private __sanitizer::AnsiColorDecorator { public: Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { } @@ -120,5 +110,4 @@ Printf("%s", d.End()); } - } // namespace __msan Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -107,6 +107,8 @@ // IO void RawWrite(const char *buffer); bool PrintsToTty(); +// Caching version of PrintsToTty(). Not thread-safe. +bool PrintsToTtyCached(); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); Index: lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_common_libcdep.cc +++ lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -20,4 +20,18 @@ return internal_isatty(report_fd) != 0; } +bool PrintsToTtyCached() { + // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color + // printing on Windows. + if (SANITIZER_WINDOWS) + return 0; + + static int cached = 0; + static bool prints_to_tty; + if (!cached) { // Not thread-safe. + prints_to_tty = PrintsToTty(); + cached = 1; + } + return prints_to_tty; +} } // namespace __sanitizer