Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[analyzer] Fix StackAddrEscapeChecker crash on temporary object fields #66493

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()();
}