@@ -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+
291316void 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 ())
0 commit comments