@@ -288,12 +288,37 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
288
288
EmitStackError (C, R, RetE);
289
289
}
290
290
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
+
291
316
void StackAddrEscapeChecker::checkEndFunction (const ReturnStmt *RS,
292
317
CheckerContext &Ctx) const {
293
318
if (!ChecksEnabled[CK_StackAddrEscapeChecker])
294
319
return ;
295
320
296
- ProgramStateRef State = Ctx.getState ();
321
+ ExplodedNode *Node = Ctx.getPredecessor ();
297
322
298
323
// Iterate over all bindings to global variables and see if it contains
299
324
// a memory region in the stack space.
@@ -315,15 +340,10 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
315
340
if (!ReferrerMemSpace || !ReferredMemSpace)
316
341
return false ;
317
342
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 ;
327
347
}
328
348
return false ;
329
349
}
@@ -352,14 +372,15 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
352
372
};
353
373
354
374
CallBack Cb (Ctx);
375
+ ProgramStateRef State = Node->getState ();
355
376
State->getStateManager ().getStoreManager ().iterBindings (State->getStore (),
356
377
Cb);
357
378
358
379
if (Cb.V .empty ())
359
380
return ;
360
381
361
382
// Generate an error node.
362
- ExplodedNode *N = Ctx.generateNonFatalErrorNode (State);
383
+ ExplodedNode *N = Ctx.generateNonFatalErrorNode (State, Node );
363
384
if (!N)
364
385
return ;
365
386
@@ -374,13 +395,13 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
374
395
375
396
// Generate a report for this bug.
376
397
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" ;
378
399
SmallString<128 > Buf;
379
400
llvm::raw_svector_ostream Out (Buf);
380
401
const SourceRange Range = genName (Out, Referred, Ctx.getASTContext ());
381
402
382
403
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"
384
405
<< CommonSuffix;
385
406
auto Report =
386
407
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str (), N);
@@ -390,28 +411,12 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
390
411
return ;
391
412
}
392
413
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 ;
409
417
}
410
- const std::string ReferrerVarName =
411
- ReferrerVar->getDecl ()->getDeclName ().getAsString ();
412
418
413
- Out << " is still referred to by the " << ReferrerMemorySpace
414
- << " variable '" << ReferrerVarName << " ' " << CommonSuffix;
419
+ Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix;
415
420
auto Report =
416
421
std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str (), N);
417
422
if (Range.isValid ())
0 commit comments