Index: compiler-rt/lib/asan/asan_errors.h =================================================================== --- compiler-rt/lib/asan/asan_errors.h +++ compiler-rt/lib/asan/asan_errors.h @@ -311,6 +311,24 @@ void Print(); }; +struct ErrorUseAfterScope : ErrorBase { + uptr pc, bp, sp; + const char *variable_name; + uptr variable_size; + // VS2013 doesn't implement unrestricted unions, so we need a trivial default + // constructor + ErrorUseAfterScope() = default; + ErrorUseAfterScope(u32 tid, uptr pc_, uptr bp_, uptr sp_, + const char *variable_name_, uptr variable_size_) + : ErrorBase(tid), + pc(pc_), + bp(bp_), + sp(sp_), + variable_name(variable_name_), + variable_size(variable_size_) {} + void Print(); +}; + // clang-format off #define ASAN_FOR_EACH_ERROR_KIND(macro) \ macro(StackOverflow) \ @@ -326,7 +344,8 @@ macro(BadParamsToAnnotateContiguousContainer) \ macro(ODRViolation) \ macro(InvalidPointerPair) \ - macro(Generic) + macro(Generic) \ + macro(UseAfterScope) // clang-format on #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name, Index: compiler-rt/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/lib/asan/asan_errors.cc +++ compiler-rt/lib/asan/asan_errors.cc @@ -493,4 +493,25 @@ PrintShadowMemoryForAddress(addr); } +void ErrorUseAfterScope::Print() { + const char *bug_type = "stack-use-after-scope"; + Decorator d; + Printf("%s", d.Warning()); + + Report( + "ERROR: AddressSanitizer: stack-use-after-scope at pc %p bp %p sp %p\n", + variable_name, variable_size, pc, bp, sp); + Printf("%s", d.EndWarning()); + scariness.Print(); + + char tname[128]; + Printf("READ of size %zu for variable '%s' thread T%d%s%s\n", variable_size, + variable_name, tid, + ThreadNameWithParenthesis(tid, tname, sizeof(tname)), d.EndAccess()); + + GET_STACK_TRACE_FATAL(pc, bp); + stack.Print(); + ReportErrorSummary(bug_type, &stack); +} + } // namespace __asan Index: compiler-rt/lib/asan/asan_report.h =================================================================== --- compiler-rt/lib/asan/asan_report.h +++ compiler-rt/lib/asan/asan_report.h @@ -70,6 +70,9 @@ void ReportODRViolation(const __asan_global *g1, u32 stack_id1, const __asan_global *g2, u32 stack_id2); +void ReportUseAfterScope(const char *variable_name, uptr variable_size, + bool fatal); + // Mac-specific errors and warnings. void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, Index: compiler-rt/lib/asan/asan_report.cc =================================================================== --- compiler-rt/lib/asan/asan_report.cc +++ compiler-rt/lib/asan/asan_report.cc @@ -355,6 +355,16 @@ return ReportInvalidPointerPair(pc, bp, sp, a1, a2); } } + +void ReportUseAfterScope(const char *variable_name, uptr variable_size, + bool fatal) { + ScopedInErrorReport in_report (fatal); + GET_CALLER_PC_BP_SP; + ErrorUseAfterScope error(GetCurrentTidOrInvalid(), pc, bp, sp, variable_name, + variable_size); + in_report.ReportError(error); +} + // ----------------------- Mac-specific reports ----------------- {{{1 void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name, Index: compiler-rt/lib/asan/asan_rtl.cc =================================================================== --- compiler-rt/lib/asan/asan_rtl.cc +++ compiler-rt/lib/asan/asan_rtl.cc @@ -255,6 +255,20 @@ } } +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_report_use_after_scope(const char *variable_name, + uptr variable_size) { + ReportUseAfterScope(variable_name, variable_size, true); +} + +extern "C" +NOINLINE INTERFACE_ATTRIBUTE +void __asan_report_use_after_scope_noabort(const char *variable_name, + uptr variable_size) { + ReportUseAfterScope(variable_name, variable_size, false); +} + // Force the linker to keep the symbols for various ASan interface functions. // We want to keep those in the executable in order to let the instrumented // dynamic libraries access the symbol even if it is not used by the executable Index: compiler-rt/test/asan/TestCases/use-after-scope-conditional.cc =================================================================== --- /dev/null +++ compiler-rt/test/asan/TestCases/use-after-scope-conditional.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx_asan -O2 -fsanitize-address-use-after-scope %s -o %t && %run %t + +// Test should not fail as access to address of my_char is done conditionally. + +int +main (int argc, char **argv) +{ + char *ptr = 0; + + if (argc == 123456789) + { + char my_char; + ptr = &my_char; + } + + if (ptr) + return *ptr; + + return 0; +}