1f5d2ef4a61e70eb2bcc3f4872e7095cf19d20163Ted Kremenek//=== StackAddrEscapeChecker.cpp ----------------------------------*- C++ -*--// 21622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// 31622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// The LLVM Compiler Infrastructure 41622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// 51622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// This file is distributed under the University of Illinois Open Source 61622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// License. See LICENSE.TXT for details. 71622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// 81622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu//===----------------------------------------------------------------------===// 91622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// 101622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// This file defines stack address leak checker, which checks if an invalid 111622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// stack address is stored into a global or heap location. See CERT DCL30-C. 121622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu// 131622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu//===----------------------------------------------------------------------===// 141622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 15027a6abdd6cedc0b8203da72eed6d15c796dce9dArgyrios Kyrtzidis#include "ClangSACheckers.h" 1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ExprCXX.h" 1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 19ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 20695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 21af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 2218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 239b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu#include "llvm/ADT/SmallString.h" 24a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h" 251622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xuusing namespace clang; 269ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 271622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 281622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xunamespace { 29ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass StackAddrEscapeChecker : public Checker< check::PreStmt<ReturnStmt>, 30344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks check::EndFunction > { 31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BuiltinBug> BT_stackleak; 32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BuiltinBug> BT_returnstack; 331622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 341622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xupublic: 35af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; 36344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks void checkEndFunction(CheckerContext &Ctx) const; 379b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xuprivate: 38af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis void EmitStackError(CheckerContext &C, const MemRegion *R, 39af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis const Expr *RetE) const; 40a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose static SourceRange genName(raw_ostream &os, const MemRegion *R, 41a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose ASTContext &Ctx); 421622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu}; 431622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu} 441622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 45a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan RoseSourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R, 46a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose ASTContext &Ctx) { 47a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Get the base region, stripping away fields and elements. 489b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu R = R->getBaseRegion(); 49a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose SourceManager &SM = Ctx.getSourceManager(); 50a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceRange range; 51a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "Address of "; 52a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 539b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu // Check if the region is a compound literal. 549b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) { 559c378f705405d37f49795d5e915989de774fe11fTed Kremenek const CompoundLiteralExpr *CL = CR->getLiteralExpr(); 56a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory associated with a compound literal " 57a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek "declared on line " 58642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << SM.getExpansionLineNumber(CL->getLocStart()) 59a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << " returned to caller"; 609b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = CL->getSourceRange(); 619b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 629b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) { 639c378f705405d37f49795d5e915989de774fe11fTed Kremenek const Expr *ARE = AR->getExpr(); 649b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu SourceLocation L = ARE->getLocStart(); 659b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = ARE->getSourceRange(); 66a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory allocated by call to alloca() on line " 67642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << SM.getExpansionLineNumber(L); 689b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 699b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) { 709b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const BlockDecl *BD = BR->getCodeRegion()->getDecl(); 719b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu SourceLocation L = BD->getLocStart(); 729b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = BD->getSourceRange(); 73a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack-allocated block declared on line " 74642116259e8df6286063a17361c20e95b5017a0aChandler Carruth << SM.getExpansionLineNumber(L); 759b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 769b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 77a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory associated with local variable '" 78a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << VR->getString() << '\''; 799b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = VR->getDecl()->getSourceRange(); 809b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 81782f63ecd124f9384f988dc7e0cf4ae1540c15f6Jeffrey Yasskin else if (const CXXTempObjectRegion *TOR = dyn_cast<CXXTempObjectRegion>(R)) { 82a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose QualType Ty = TOR->getValueType().getLocalUnqualifiedType(); 83a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose os << "stack memory associated with temporary object of type '"; 84a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose Ty.print(os, Ctx.getPrintingPolicy()); 85a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose os << "'"; 86782f63ecd124f9384f988dc7e0cf4ae1540c15f6Jeffrey Yasskin range = TOR->getExpr()->getSourceRange(); 87782f63ecd124f9384f988dc7e0cf4ae1540c15f6Jeffrey Yasskin } 889b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else { 89b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid region in ReturnStackAddressChecker."); 90a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek } 91a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 92a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek return range; 93a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek} 94a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 95f5d2ef4a61e70eb2bcc3f4872e7095cf19d20163Ted Kremenekvoid StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R, 96af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis const Expr *RetE) const { 97d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 98a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 99a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (!N) 1009b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 1019b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 102a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (!BT_returnstack) 103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_returnstack.reset( 104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new BuiltinBug(this, "Return of address to stack-allocated memory")); 105a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 106a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Generate a report for this bug. 107f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<512> buf; 108a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::raw_svector_ostream os(buf); 109a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose SourceRange range = genName(os, R, C.getASTContext()); 110a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << " returned to caller"; 111e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_returnstack, os.str(), N); 1129b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu report->addRange(RetE->getSourceRange()); 1139b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (range.isValid()) 1149b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu report->addRange(range); 1159b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 116785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(report); 117a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman} 1189b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 119f5d2ef4a61e70eb2bcc3f4872e7095cf19d20163Ted Kremenekvoid StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, 1207e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek CheckerContext &C) const { 1219b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1229b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const Expr *RetE = RS->getRetValue(); 1239b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (!RetE) 1249b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 12573212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose RetE = RetE->IgnoreParens(); 126c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose 127c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose const LocationContext *LCtx = C.getLocationContext(); 128c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose SVal V = C.getState()->getSVal(RetE, LCtx); 1299b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const MemRegion *R = V.getAsRegion(); 1309b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1317e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek if (!R) 1327e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek return; 1339b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1347e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek const StackSpaceRegion *SS = 1357e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek dyn_cast_or_null<StackSpaceRegion>(R->getMemorySpace()); 1367e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek 1377e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek if (!SS) 1387e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek return; 139f85e193739c953358c865005855253af4f68a497John McCall 1407e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek // Return stack memory in an ancestor stack frame is fine. 141c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose const StackFrameContext *CurFrame = LCtx->getCurrentStackFrame(); 142c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose const StackFrameContext *MemFrame = SS->getStackFrame(); 143c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose if (MemFrame != CurFrame) 1449b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 1457e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek 1467e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek // Automatic reference counting automatically copies blocks. 1474e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (C.getASTContext().getLangOpts().ObjCAutoRefCount && 1487e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek isa<BlockDataRegion>(R)) 1497e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek return; 1507e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek 151c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose // Returning a record by value is fine. (In this case, the returned 15273212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose // expression will be a copy-constructor, possibly wrapped in an 15373212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose // ExprWithCleanups node.) 15473212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose if (const ExprWithCleanups *Cleanup = dyn_cast<ExprWithCleanups>(RetE)) 15573212dff6437d409e0c1b779fdcac2f4f98ca8b0Jordan Rose RetE = Cleanup->getSubExpr(); 156c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose if (isa<CXXConstructExpr>(RetE) && RetE->getType()->isRecordType()) 157c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose return; 158c210cb7a358d14cdd93b58562f33ff5ed2d895c1Jordan Rose 1597e8678314cf19f28cfddb2d9d0567d993073ec7eTed Kremenek EmitStackError(C, R, RetE); 1609b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu} 1611622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 162344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaksvoid StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const { 1638bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Ctx.getState(); 164551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 165551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // Iterate over all bindings to global variables and see if it contains 166551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // a memory region in the stack space. 167551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek class CallBack : public StoreManager::BindingsHandler { 168551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek private: 169af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks CheckerContext &Ctx; 170551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek const StackFrameContext *CurSFC; 171551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek public: 1725f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V; 173551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 174af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks CallBack(CheckerContext &CC) : 175af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks Ctx(CC), 17639ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks CurSFC(CC.getLocationContext()->getCurrentStackFrame()) 177af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks {} 178551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 179551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek bool HandleBinding(StoreManager &SMgr, Store store, 180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const MemRegion *region, SVal val) override { 181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 182551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!isa<GlobalsSpaceRegion>(region->getMemorySpace())) 183551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 184551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 185551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek const MemRegion *vR = val.getAsRegion(); 186551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!vR) 187551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 188f85e193739c953358c865005855253af4f68a497John McCall 189f85e193739c953358c865005855253af4f68a497John McCall // Under automated retain release, it is okay to assign a block 190f85e193739c953358c865005855253af4f68a497John McCall // directly to a global variable. 1914e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount && 192f85e193739c953358c865005855253af4f68a497John McCall isa<BlockDataRegion>(vR)) 193f85e193739c953358c865005855253af4f68a497John McCall return true; 194f85e193739c953358c865005855253af4f68a497John McCall 195551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (const StackSpaceRegion *SSR = 196551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) { 197551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // If the global variable holds a location in the current stack frame, 198551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // record the binding to emit a warning. 199a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (SSR->getStackFrame() == CurSFC) 200a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek V.push_back(std::make_pair(region, vR)); 2011622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu } 202551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 203551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 2041622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu } 205551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek }; 206551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 207af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks CallBack cb(Ctx); 208551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb); 209a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 210a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (cb.V.empty()) 211551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return; 212551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 213551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // Generate an error node. 2140bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks ExplodedNode *N = Ctx.addTransition(state); 215551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!N) 216551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return; 217a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 218551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!BT_stackleak) 219af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis BT_stackleak.reset( 220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new BuiltinBug(this, "Stack address stored into global variable", 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Stack address was saved into a global variable. " 222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "This is dangerous because the address will become " 223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "invalid after returning from the function")); 224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 225a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek for (unsigned i = 0, e = cb.V.size(); i != e; ++i) { 226a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Generate a report for this bug. 227f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<512> buf; 228a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::raw_svector_ostream os(buf); 229a0e6e6dd37f4acee8477c106d5e5679de015d120Jordan Rose SourceRange range = genName(os, cb.V[i].second, Ctx.getASTContext()); 230a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << " is still referred to by the global variable '"; 231a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion()); 232b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << *VR->getDecl() 233a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << "' upon returning to the caller. This will be a dangling reference"; 234e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_stackleak, os.str(), N); 235a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (range.isValid()) 236a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek report->addRange(range); 237a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 238785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose Ctx.emitReport(report); 239a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek } 2401622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu} 241af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis 242f5d2ef4a61e70eb2bcc3f4872e7095cf19d20163Ted Kremenekvoid ento::registerStackAddrEscapeChecker(CheckerManager &mgr) { 243f5d2ef4a61e70eb2bcc3f4872e7095cf19d20163Ted Kremenek mgr.registerChecker<StackAddrEscapeChecker>(); 244af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis} 245