Index: libsanitizer/asan/asan_errors.h =================================================================== --- libsanitizer/asan/asan_errors.h +++ libsanitizer/asan/asan_errors.h @@ -294,6 +294,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(); +}; + struct ErrorGeneric : ErrorBase { AddressDescription addr_description; uptr pc, bp, sp; @@ -324,7 +342,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: libsanitizer/asan/asan_errors.cc =================================================================== --- libsanitizer/asan/asan_errors.cc +++ libsanitizer/asan/asan_errors.cc @@ -279,6 +279,27 @@ ReportErrorSummary(bug_type, &stack); } +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); +} + static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) { return s[-1] > 127 && s[1] > 127; } Index: libsanitizer/asan/asan_report.h =================================================================== --- libsanitizer/asan/asan_report.h +++ libsanitizer/asan/asan_report.h @@ -68,6 +68,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: libsanitizer/asan/asan_report.cc =================================================================== --- libsanitizer/asan/asan_report.cc +++ libsanitizer/asan/asan_report.cc @@ -353,6 +353,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: libsanitizer/asan/asan_rtl.cc =================================================================== --- libsanitizer/asan/asan_rtl.cc +++ libsanitizer/asan/asan_rtl.cc @@ -253,6 +253,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