Skip to content

Commit

Permalink
[analyzer] Fix StackAddrEscapeChecker crash on temporary object fields
Browse files Browse the repository at this point in the history
Basically, the issue was that we should have unwrap the base region
before we special handle temp object regions.

Fixes #66221
  • Loading branch information
steakhal committed Sep 20, 2023
1 parent 522c1d0 commit 895826d
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 895826d

Please sign in to comment.