Index: compiler-rt/lib/asan/asan_descriptions.h =================================================================== --- compiler-rt/lib/asan/asan_descriptions.h +++ compiler-rt/lib/asan/asan_descriptions.h @@ -43,43 +43,72 @@ class Decorator : public __sanitizer::SanitizerCommonDecorator { public: - Decorator() : SanitizerCommonDecorator() {} + Decorator() : SanitizerCommonDecorator() { + last_decoration = __sanitizer::SanitizerCommonDecorator::Default(); + } + + const char *Default() { + last_decoration = __sanitizer::SanitizerCommonDecorator::Default(); + return last_decoration; + } + const char *Access() { return Blue(); } const char *Location() { return Green(); } const char *Allocation() { return Magenta(); } const char *ShadowByte(u8 byte) { + const char *new_decoration; switch (byte) { case kAsanHeapLeftRedzoneMagic: case kAsanArrayCookieMagic: - return Red(); + new_decoration = Red(); + break; case kAsanHeapFreeMagic: - return Magenta(); + new_decoration = Magenta(); + break; case kAsanStackLeftRedzoneMagic: case kAsanStackMidRedzoneMagic: case kAsanStackRightRedzoneMagic: - return Red(); + new_decoration = Red(); + break; case kAsanStackAfterReturnMagic: - return Magenta(); + new_decoration = Magenta(); + break; case kAsanInitializationOrderMagic: - return Cyan(); + new_decoration = Cyan(); + break; case kAsanUserPoisonedMemoryMagic: case kAsanContiguousContainerOOBMagic: case kAsanAllocaLeftMagic: case kAsanAllocaRightMagic: - return Blue(); + new_decoration = Blue(); + break; case kAsanStackUseAfterScopeMagic: - return Magenta(); + new_decoration = Magenta(); + break; case kAsanGlobalRedzoneMagic: - return Red(); + new_decoration = Red(); + break; case kAsanInternalHeapMagic: - return Yellow(); + new_decoration = Yellow(); + break; case kAsanIntraObjectRedzone: - return Yellow(); + new_decoration = Yellow(); + break; default: - return Default(); + new_decoration = Default(); } + + // Optimization: Don't return a decoration if it hasn't changed. + if (last_decoration == new_decoration) + return ""; + + last_decoration = new_decoration; + return new_decoration; } + + private: + const char *last_decoration; }; enum ShadowKind : u8 { Index: compiler-rt/lib/asan/asan_descriptions.cc =================================================================== --- compiler-rt/lib/asan/asan_descriptions.cc +++ compiler-rt/lib/asan/asan_descriptions.cc @@ -147,10 +147,10 @@ "%p is located somewhere around (this is AddressSanitizer bug!)", (void *)descr.bad_addr); } - str.append(" %zu-byte region [%p,%p)\n", descr.chunk_size, + str.append(" %zu-byte region [%p,%p)%s\n", descr.chunk_size, (void *)descr.chunk_begin, - (void *)(descr.chunk_begin + descr.chunk_size)); - str.append("%s", d.Default()); + (void *)(descr.chunk_begin + descr.chunk_size), + d.Default()); Printf("%s", str.data()); } Index: compiler-rt/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/lib/asan/asan_errors.cc +++ compiler-rt/lib/asan/asan_errors.cc @@ -479,65 +479,91 @@ "AddressSanitizerContainerOverflow.\n"); } -static void PrintShadowByte(InternalScopedString *str, const char *before, - u8 byte, const char *after = "\n") { - PrintMemoryByte(str, before, byte, /*in_shadow*/true, after); +static void PrintShadowByte(InternalScopedString *str, Decorator *d, + const char *before, u8 byte, const char *after = "\n") { + PrintMemoryByte(str, d, before, byte, after); +} + +static void PrintLegendEntry(InternalScopedString *str, Decorator *d, + const char *text, u8 byte) { + PrintShadowByte(str, d, text, byte, ""); + str->append(d->Default()); + str->append("\n"); } static void PrintLegend(InternalScopedString *str) { + Decorator d; str->append( "Shadow byte legend (one shadow byte represents %d " "application bytes):\n", (int)SHADOW_GRANULARITY); - PrintShadowByte(str, " Addressable: ", 0); + PrintShadowByte(str, &d, " Addressable: ", 0); str->append(" Partially addressable: "); - for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " "); + for (u8 i = 1; i < SHADOW_GRANULARITY; i++) + PrintShadowByte(str, &d, "", i, " "); str->append("\n"); - PrintShadowByte(str, " Heap left redzone: ", - kAsanHeapLeftRedzoneMagic); - PrintShadowByte(str, " Freed heap region: ", kAsanHeapFreeMagic); - PrintShadowByte(str, " Stack left redzone: ", - kAsanStackLeftRedzoneMagic); - PrintShadowByte(str, " Stack mid redzone: ", - kAsanStackMidRedzoneMagic); - PrintShadowByte(str, " Stack right redzone: ", - kAsanStackRightRedzoneMagic); - PrintShadowByte(str, " Stack after return: ", - kAsanStackAfterReturnMagic); - PrintShadowByte(str, " Stack use after scope: ", - kAsanStackUseAfterScopeMagic); - PrintShadowByte(str, " Global redzone: ", kAsanGlobalRedzoneMagic); - PrintShadowByte(str, " Global init order: ", - kAsanInitializationOrderMagic); - PrintShadowByte(str, " Poisoned by user: ", - kAsanUserPoisonedMemoryMagic); - PrintShadowByte(str, " Container overflow: ", - kAsanContiguousContainerOOBMagic); - PrintShadowByte(str, " Array cookie: ", - kAsanArrayCookieMagic); - PrintShadowByte(str, " Intra object redzone: ", - kAsanIntraObjectRedzone); - PrintShadowByte(str, " ASan internal: ", kAsanInternalHeapMagic); - PrintShadowByte(str, " Left alloca redzone: ", kAsanAllocaLeftMagic); - PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); - PrintShadowByte(str, " Shadow gap: ", kAsanShadowGap); + str->append("\n"); + PrintLegendEntry(str, &d, " Heap left redzone: ", + kAsanHeapLeftRedzoneMagic); + PrintLegendEntry(str, &d, " Freed heap region: ", + kAsanHeapFreeMagic); + PrintLegendEntry(str, &d, " Stack left redzone: ", + kAsanStackLeftRedzoneMagic); + PrintLegendEntry(str, &d, " Stack mid redzone: ", + kAsanStackMidRedzoneMagic); + PrintLegendEntry(str, &d, " Stack right redzone: ", + kAsanStackRightRedzoneMagic); + PrintLegendEntry(str, &d, " Stack after return: ", + kAsanStackAfterReturnMagic); + PrintLegendEntry(str, &d, " Stack use after scope: ", + kAsanStackUseAfterScopeMagic); + PrintLegendEntry(str, &d, " Global redzone: ", + kAsanGlobalRedzoneMagic); + PrintLegendEntry(str, &d, " Global init order: ", + kAsanInitializationOrderMagic); + PrintLegendEntry(str, &d, " Poisoned by user: ", + kAsanUserPoisonedMemoryMagic); + PrintLegendEntry(str, &d, " Container overflow: ", + kAsanContiguousContainerOOBMagic); + PrintLegendEntry(str, &d, " Array cookie: ", + kAsanArrayCookieMagic); + PrintLegendEntry(str, &d, " Intra object redzone: ", + kAsanIntraObjectRedzone); + PrintLegendEntry(str, &d, " ASan internal: ", + kAsanInternalHeapMagic); + PrintLegendEntry(str, &d, " Left alloca redzone: ", + kAsanAllocaLeftMagic); + PrintLegendEntry(str, &d, " Right alloca redzone: ", + kAsanAllocaRightMagic); + PrintLegendEntry(str, &d, " Shadow gap: ", + kAsanShadowGap); } -static void PrintShadowBytes(InternalScopedString *str, const char *before, - u8 *bytes, u8 *guilty, uptr n) { - Decorator d; +static void PrintShadowBytes(InternalScopedString *str, Decorator *d, + const char *before, u8 *bytes, u8 *guilty, uptr n) { if (before) str->append("%s%p:", before, bytes); for (uptr i = 0; i < n; i++) { u8 *p = bytes + i; - const char *before = - p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " "; - const char *after = p == guilty ? "]" : ""; - PrintShadowByte(str, before, *p, after); + const char *before; + const char *after; + if (p == guilty) { + str->append(d->Default()); + before = "["; + PrintShadowByte(str, d, before, *p, ""); + str->append(d->Default()); + str->append("]"); + } else { + before = (p - 1 == guilty && i != 0) ? "" : " "; + after = ""; + PrintShadowByte(str, d, before, *p, after); + } } + + str->append(d->Default()); str->append("\n"); } -static void PrintShadowMemoryForAddress(uptr addr) { +static void PrintShadowMemoryForAddress(uptr addr, Decorator *d) { if (!AddrIsInMem(addr)) return; uptr shadow_addr = MemToShadow(addr); const uptr n_bytes_per_row = 16; @@ -551,7 +577,7 @@ // space. if (!AddrIsInShadow(row_shadow_addr)) continue; const char *prefix = (i == 0) ? "=>" : " "; - PrintShadowBytes(&str, prefix, (u8 *)row_shadow_addr, (u8 *)shadow_addr, + PrintShadowBytes(&str, d, prefix, (u8 *)row_shadow_addr, (u8 *)shadow_addr, n_bytes_per_row); } if (flags()->print_legend) PrintLegend(&str); @@ -562,8 +588,8 @@ Decorator d; Printf("%s", d.Error()); uptr addr = addr_description.Address(); - Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n", - bug_descr, (void *)addr, pc, bp, sp); + Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p%s\n", + bug_descr, (void *)addr, pc, bp, sp, d.Default()); Printf("%s", d.Default()); Printf("%s%s of size %zu at %p thread %s%s\n", d.Access(), @@ -580,7 +606,7 @@ if (shadow_val == kAsanContiguousContainerOOBMagic) PrintContainerOverflowHint(); ReportErrorSummary(bug_descr, &stack); - PrintShadowMemoryForAddress(addr); + PrintShadowMemoryForAddress(addr, &d); } } // namespace __asan Index: compiler-rt/lib/asan/asan_report.h =================================================================== --- compiler-rt/lib/asan/asan_report.h +++ compiler-rt/lib/asan/asan_report.h @@ -16,6 +16,7 @@ #define ASAN_REPORT_H #include "asan_allocator.h" +#include "asan_descriptions.h" #include "asan_internal.h" #include "asan_thread.h" @@ -38,8 +39,8 @@ void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g); void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g); -void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte, - bool in_shadow, const char *after = "\n"); +void PrintMemoryByte(InternalScopedString *str, Decorator *d, + const char *before, u8 byte, const char *after); // The following functions prints address description depending // on the memory type (shadow/heap/stack/global). Index: compiler-rt/lib/asan/asan_report.cc =================================================================== --- compiler-rt/lib/asan/asan_report.cc +++ compiler-rt/lib/asan/asan_report.cc @@ -56,12 +56,10 @@ // ---------------------- Helper functions ----------------------- {{{1 -void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte, - bool in_shadow, const char *after) { - Decorator d; - str->append("%s%s%x%x%s%s", before, - in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), byte >> 4, - byte & 15, d.Default(), after); +void PrintMemoryByte(InternalScopedString *str, Decorator *d, + const char *before, u8 byte, const char *after) { + str->append("%s%s%x%x%s", before, d->ShadowByte(byte), byte >> 4, byte & 15, + after); } static void PrintZoneForPointer(uptr ptr, uptr zone_ptr, Index: compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h +++ compiler-rt/lib/sanitizer_common/sanitizer_report_decorator.h @@ -26,7 +26,7 @@ public: SanitizerCommonDecorator() : ansi_(ColorizeReports()) {} const char *Bold() const { return ansi_ ? "\033[1m" : ""; } - const char *Default() const { return ansi_ ? "\033[1m\033[0m" : ""; } + const char *Default() const { return ansi_ ? "\033[0m" : ""; } const char *Warning() const { return Red(); } const char *Error() const { return Red(); } const char *MemoryByte() const { return Magenta(); }