Skip to content

Commit 73dcbd4

Browse files
authored
[analyzer] Fix StackAddrEscapeChecker crash on temporary object fields (#66493)
Basically, the issue was that we should have unwrapped the base region before we special handle temp object regions. Fixes #66221 I also decided to add some extra range information to the diagnostics to make it consistent with the other reporting path.
1 parent 69183f8 commit 73dcbd4

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
369369
"Stack address stored into global variable");
370370

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

375375
// Generate a report for this bug.
@@ -384,6 +384,8 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
384384
<< CommonSuffix;
385385
auto Report =
386386
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
387+
if (Range.isValid())
388+
Report->addRange(Range);
387389
Ctx.emitReport(std::move(Report));
388390
return;
389391
}
@@ -397,8 +399,14 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
397399
return "stack";
398400
}(Referrer->getMemorySpace());
399401

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

clang/test/Analysis/stackaddrleak.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
2+
3+
using size_t = decltype(sizeof(int));
4+
void *operator new(size_t, void *p) { return p; }
5+
6+
struct myfunction {
7+
union storage_t {
8+
char buffer[100];
9+
size_t max_align;
10+
} storage;
11+
12+
template <typename Func> myfunction(Func fn) {
13+
new (&storage.buffer) Func(fn);
14+
}
15+
void operator()();
16+
};
17+
18+
myfunction create_func() {
19+
int n;
20+
auto c = [&n] {};
21+
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}}
22+
}
23+
void gh_66221() {
24+
create_func()();
25+
}

0 commit comments

Comments
 (0)