@@ -288,6 +288,23 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
288
288
EmitStackError (C, R, RetE);
289
289
}
290
290
291
+ static const MemSpaceRegion *getStackOrGlobalSpaceRegion (const MemRegion *R) {
292
+ assert (R);
293
+ if (const auto *MemSpace = R->getMemorySpace ()) {
294
+ if (const auto *SSR = MemSpace->getAs <StackSpaceRegion>())
295
+ return SSR;
296
+ if (const auto *GSR = MemSpace->getAs <GlobalsSpaceRegion>())
297
+ return GSR;
298
+ }
299
+ // If R describes a lambda capture, it will be a symbolic region
300
+ // referring to a field region of another symbolic region.
301
+ if (const auto *SymReg = R->getBaseRegion ()->getAs <SymbolicRegion>()) {
302
+ if (const auto *OriginReg = SymReg->getSymbol ()->getOriginRegion ())
303
+ return getStackOrGlobalSpaceRegion (OriginReg);
304
+ }
305
+ return nullptr ;
306
+ }
307
+
291
308
std::optional<std::string> printReferrer (const MemRegion *Referrer) {
292
309
assert (Referrer);
293
310
const StringRef ReferrerMemorySpace = [](const MemSpaceRegion *Space) {
@@ -297,20 +314,31 @@ std::optional<std::string> printReferrer(const MemRegion *Referrer) {
297
314
return " global" ;
298
315
assert (isa<StackSpaceRegion>(Space));
299
316
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.
317
+ }(getStackOrGlobalSpaceRegion (Referrer));
318
+
319
+ while (!Referrer->canPrintPretty ()) {
320
+ if (const auto *SymReg = dyn_cast<SymbolicRegion>(Referrer);
321
+ SymReg && SymReg->getSymbol ()->getOriginRegion ()) {
322
+ Referrer = SymReg->getSymbol ()->getOriginRegion ()->getBaseRegion ();
323
+ } else if (isa<CXXThisRegion>(Referrer)) {
324
+ // Skip members of a class, it is handled in CheckExprLifetime.cpp as
325
+ // warn_bind_ref_member_to_parameter or
326
+ // warn_init_ptr_member_to_parameter_addr
327
+ return std::nullopt;
328
+ } else {
329
+ Referrer->dump ();
330
+ assert (false && " Unexpected referrer region type." );
331
+ return std::nullopt;
332
+ }
309
333
}
310
- const std::string ReferrerVarName =
311
- ReferrerVar-> getDecl ()-> getDeclName (). getAsString ( );
334
+ assert (Referrer);
335
+ assert (Referrer-> canPrintPretty () );
312
336
313
- return (ReferrerMemorySpace + " variable '" + ReferrerVarName + " '" ).str ();
337
+ std::string buf;
338
+ llvm::raw_string_ostream os (buf);
339
+ os << ReferrerMemorySpace << " variable " ;
340
+ Referrer->printPretty (os);
341
+ return buf;
314
342
}
315
343
316
344
void StackAddrEscapeChecker::checkEndFunction (const ReturnStmt *RS,
@@ -332,16 +360,20 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
332
360
// / referred by an other stack variable from different stack frame.
333
361
bool checkForDanglingStackVariable (const MemRegion *Referrer,
334
362
const MemRegion *Referred) {
335
- const auto *ReferrerMemSpace =
336
- Referrer->getMemorySpace ()->getAs <StackSpaceRegion>();
363
+ const auto *ReferrerMemSpace = getStackOrGlobalSpaceRegion (Referrer);
337
364
const auto *ReferredMemSpace =
338
365
Referred->getMemorySpace ()->getAs <StackSpaceRegion>();
339
366
340
367
if (!ReferrerMemSpace || !ReferredMemSpace)
341
368
return false ;
342
369
370
+ const auto *ReferrerStackSpace =
371
+ ReferrerMemSpace->getAs <StackSpaceRegion>();
372
+ if (!ReferrerStackSpace)
373
+ return false ;
374
+
343
375
if (ReferredMemSpace->getStackFrame () == PoppedFrame &&
344
- ReferrerMemSpace ->getStackFrame ()->isParentOf (PoppedFrame)) {
376
+ ReferrerStackSpace ->getStackFrame ()->isParentOf (PoppedFrame)) {
345
377
V.emplace_back (Referrer, Referred);
346
378
return true ;
347
379
}
@@ -387,7 +419,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
387
419
if (!BT_stackleak)
388
420
BT_stackleak =
389
421
std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
390
- " Stack address stored into global variable " );
422
+ " Stack address leaks outside of stack frame " );
391
423
392
424
for (const auto &P : Cb.V ) {
393
425
const MemRegion *Referrer = P.first ->getBaseRegion ();
0 commit comments