Skip to content

Commit

Permalink
[analyzer] Fix StackAddrEscapeChecker crash on temporary object fields (
Browse files Browse the repository at this point in the history
llvm#66493)

Basically, the issue was that we should have unwrapped the
base region before we special handle temp object regions.

Fixes llvm#66221

I also decided to add some extra range information to the diagnostics
to make it consistent with the other reporting path.
  • Loading branch information
steakhal authored Sep 20, 2023
1 parent 69183f8 commit 73dcbd4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
14 changes: 11 additions & 3 deletions clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
"Stack address stored into global variable");

for (const auto &P : Cb.V) {
const MemRegion *Referrer = P.first;
const MemRegion *Referrer = P.first->getBaseRegion();
const MemRegion *Referred = P.second;

// Generate a report for this bug.
Expand All @@ -384,6 +384,8 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
<< CommonSuffix;
auto Report =
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
if (Range.isValid())
Report->addRange(Range);
Ctx.emitReport(std::move(Report));
return;
}
Expand All @@ -397,8 +399,14 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
return "stack";
}(Referrer->getMemorySpace());

// This cast supposed to succeed.
const VarRegion *ReferrerVar = cast<VarRegion>(Referrer->getBaseRegion());
// We should really only have VarRegions here.
// Anything else is really surprising, and we should get notified if such
// ever happens.
const auto *ReferrerVar = dyn_cast<VarRegion>(Referrer);
if (!ReferrerVar) {
assert(false && "We should have a VarRegion here");
continue; // Defensively skip this one.
}
const std::string ReferrerVarName =
ReferrerVar->getDecl()->getDeclName().getAsString();

Expand Down
25 changes: 25 additions & 0 deletions clang/test/Analysis/stackaddrleak.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s

using size_t = decltype(sizeof(int));
void *operator new(size_t, void *p) { return p; }

struct myfunction {
union storage_t {
char buffer[100];
size_t max_align;
} storage;

template <typename Func> myfunction(Func fn) {
new (&storage.buffer) Func(fn);
}
void operator()();
};

myfunction create_func() {
int n;
auto c = [&n] {};
return c; // expected-warning {{Address of stack memory associated with local variable 'n' is still referred to by a temporary object on the stack upon returning to the caller. This will be a dangling reference}}
}
void gh_66221() {
create_func()();
}

0 comments on commit 73dcbd4

Please sign in to comment.