Skip to content

Commit 57a9efc

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:2f91e98120f168b7ded6cb34d546dba178515cc4 into amd-gfx:58ed5842fd7a
Local branch amd-gfx 58ed584 Merged main:4549a8d251cfa91cc6230139595f0b7efdf199d9 into amd-gfx:757aa7b5f1a5 Remote branch main 2f91e98 [RISCV] Mark symbols used in inline asm for relocations as referenced (llvm#104925)
2 parents 58ed584 + 2f91e98 commit 57a9efc

File tree

25 files changed

+2616
-1196
lines changed

25 files changed

+2616
-1196
lines changed

clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,37 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
288288
EmitStackError(C, R, RetE);
289289
}
290290

291+
std::optional<std::string> printReferrer(const MemRegion *Referrer) {
292+
assert(Referrer);
293+
const StringRef ReferrerMemorySpace = [](const MemSpaceRegion *Space) {
294+
if (isa<StaticGlobalSpaceRegion>(Space))
295+
return "static";
296+
if (isa<GlobalsSpaceRegion>(Space))
297+
return "global";
298+
assert(isa<StackSpaceRegion>(Space));
299+
return "stack";
300+
}(Referrer->getMemorySpace());
301+
302+
// We should really only have VarRegions here.
303+
// Anything else is really surprising, and we should get notified if such
304+
// ever happens.
305+
const auto *ReferrerVar = dyn_cast<VarRegion>(Referrer);
306+
if (!ReferrerVar) {
307+
assert(false && "We should have a VarRegion here");
308+
return std::nullopt; // Defensively skip this one.
309+
}
310+
const std::string ReferrerVarName =
311+
ReferrerVar->getDecl()->getDeclName().getAsString();
312+
313+
return (ReferrerMemorySpace + " variable '" + ReferrerVarName + "'").str();
314+
}
315+
291316
void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
292317
CheckerContext &Ctx) const {
293318
if (!ChecksEnabled[CK_StackAddrEscapeChecker])
294319
return;
295320

296-
ProgramStateRef State = Ctx.getState();
321+
ExplodedNode *Node = Ctx.getPredecessor();
297322

298323
// Iterate over all bindings to global variables and see if it contains
299324
// a memory region in the stack space.
@@ -315,15 +340,10 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
315340
if (!ReferrerMemSpace || !ReferredMemSpace)
316341
return false;
317342

318-
const auto *ReferrerFrame = ReferrerMemSpace->getStackFrame();
319-
const auto *ReferredFrame = ReferredMemSpace->getStackFrame();
320-
321-
if (ReferrerMemSpace && ReferredMemSpace) {
322-
if (ReferredFrame == PoppedFrame &&
323-
ReferrerFrame->isParentOf(PoppedFrame)) {
324-
V.emplace_back(Referrer, Referred);
325-
return true;
326-
}
343+
if (ReferredMemSpace->getStackFrame() == PoppedFrame &&
344+
ReferrerMemSpace->getStackFrame()->isParentOf(PoppedFrame)) {
345+
V.emplace_back(Referrer, Referred);
346+
return true;
327347
}
328348
return false;
329349
}
@@ -352,14 +372,15 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
352372
};
353373

354374
CallBack Cb(Ctx);
375+
ProgramStateRef State = Node->getState();
355376
State->getStateManager().getStoreManager().iterBindings(State->getStore(),
356377
Cb);
357378

358379
if (Cb.V.empty())
359380
return;
360381

361382
// Generate an error node.
362-
ExplodedNode *N = Ctx.generateNonFatalErrorNode(State);
383+
ExplodedNode *N = Ctx.generateNonFatalErrorNode(State, Node);
363384
if (!N)
364385
return;
365386

@@ -374,13 +395,13 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
374395

375396
// Generate a report for this bug.
376397
const StringRef CommonSuffix =
377-
"upon returning to the caller. This will be a dangling reference";
398+
" upon returning to the caller. This will be a dangling reference";
378399
SmallString<128> Buf;
379400
llvm::raw_svector_ostream Out(Buf);
380401
const SourceRange Range = genName(Out, Referred, Ctx.getASTContext());
381402

382403
if (isa<CXXTempObjectRegion, CXXLifetimeExtendedObjectRegion>(Referrer)) {
383-
Out << " is still referred to by a temporary object on the stack "
404+
Out << " is still referred to by a temporary object on the stack"
384405
<< CommonSuffix;
385406
auto Report =
386407
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
@@ -390,28 +411,12 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
390411
return;
391412
}
392413

393-
const StringRef ReferrerMemorySpace = [](const MemSpaceRegion *Space) {
394-
if (isa<StaticGlobalSpaceRegion>(Space))
395-
return "static";
396-
if (isa<GlobalsSpaceRegion>(Space))
397-
return "global";
398-
assert(isa<StackSpaceRegion>(Space));
399-
return "stack";
400-
}(Referrer->getMemorySpace());
401-
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.
414+
auto ReferrerVariable = printReferrer(Referrer);
415+
if (!ReferrerVariable) {
416+
continue;
409417
}
410-
const std::string ReferrerVarName =
411-
ReferrerVar->getDecl()->getDeclName().getAsString();
412418

413-
Out << " is still referred to by the " << ReferrerMemorySpace
414-
<< " variable '" << ReferrerVarName << "' " << CommonSuffix;
419+
Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
415420
auto Report =
416421
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
417422
if (Range.isValid())

clang/test/Analysis/stack-addr-ps.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,34 @@ void callTestRegister(void) {
9595
char buf[20];
9696
testRegister(buf); // no-warning
9797
}
98+
99+
void top_level_leaking(int **out) {
100+
int local = 42;
101+
*out = &local; // no-warning FIXME
102+
}
103+
104+
void callee_leaking_via_param(int **out) {
105+
int local = 1;
106+
*out = &local;
107+
// expected-warning@-1{{Address of stack memory associated with local variable 'local' is still referred to by the stack variable 'ptr'}}
108+
}
109+
110+
void caller_for_leaking_callee() {
111+
int *ptr = 0;
112+
callee_leaking_via_param(&ptr);
113+
}
114+
115+
void callee_nested_leaking(int **out) {
116+
int local = 1;
117+
*out = &local;
118+
// expected-warning@-1{{Address of stack memory associated with local variable 'local' is still referred to by the stack variable 'ptr'}}
119+
}
120+
121+
void caller_mid_for_nested_leaking(int **mid) {
122+
callee_nested_leaking(mid);
123+
}
124+
125+
void caller_for_nested_leaking() {
126+
int *ptr = 0;
127+
caller_mid_for_nested_leaking(&ptr);
128+
}

0 commit comments

Comments
 (0)