StackAddrEscapeChecker.cpp revision 9ef6537a894c33003359b1f9b9676e9178e028b7
11622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu//=== StackAddrLeakChecker.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 15d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include "ExprEngineInternalChecks.h" 1698cabbad47a4d9db6b7e95c950d3302c110d1b02Argyrios Kyrtzidis#include "clang/GR/BugReporter/BugType.h" 1798cabbad47a4d9db6b7e95c950d3302c110d1b02Argyrios Kyrtzidis#include "clang/GR/PathSensitive/CheckerVisitor.h" 1898cabbad47a4d9db6b7e95c950d3302c110d1b02Argyrios Kyrtzidis#include "clang/GR/PathSensitive/GRState.h" 199b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu#include "clang/Basic/SourceManager.h" 209b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu#include "llvm/ADT/SmallString.h" 211622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xuusing namespace clang; 229ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 231622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 241622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xunamespace { 259b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xuclass StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> { 261622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu BuiltinBug *BT_stackleak; 279b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu BuiltinBug *BT_returnstack; 281622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 291622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xupublic: 309b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {} 311622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu static void *getTag() { 321622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu static int x; 331622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu return &x; 341622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu } 359b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS); 36d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis void evalEndPath(EndPathNodeBuilder &B, void *tag, ExprEngine &Eng); 379b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xuprivate: 389b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE); 39a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R, 40a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceManager &SM); 411622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu}; 421622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu} 431622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 449ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekvoid ento::RegisterStackAddrLeakChecker(ExprEngine &Eng) { 451622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu Eng.registerCheck(new StackAddrLeakChecker()); 461622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu} 479b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 48a8166156a6414ddd6a68514dc4f48e95d2259977Ted KremenekSourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os, 49a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek const MemRegion *R, 50a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceManager &SM) { 51a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Get the base region, stripping away fields and elements. 529b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu R = R->getBaseRegion(); 53a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceRange range; 54a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "Address of "; 55a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 569b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu // Check if the region is a compound literal. 579b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) { 589b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const CompoundLiteralExpr* CL = CR->getLiteralExpr(); 59a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory associated with a compound literal " 60a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek "declared on line " 61a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << SM.getInstantiationLineNumber(CL->getLocStart()) 62a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << " returned to caller"; 639b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = CL->getSourceRange(); 649b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 659b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) { 669b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const Expr* ARE = AR->getExpr(); 679b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu SourceLocation L = ARE->getLocStart(); 689b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = ARE->getSourceRange(); 69a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory allocated by call to alloca() on line " 70a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << SM.getInstantiationLineNumber(L); 719b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 729b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) { 739b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const BlockDecl *BD = BR->getCodeRegion()->getDecl(); 749b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu SourceLocation L = BD->getLocStart(); 759b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = BD->getSourceRange(); 76a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack-allocated block declared on line " 77a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << SM.getInstantiationLineNumber(L); 789b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 799b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { 80a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << "stack memory associated with local variable '" 81a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << VR->getString() << '\''; 829b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu range = VR->getDecl()->getSourceRange(); 839b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 849b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu else { 859b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu assert(false && "Invalid region in ReturnStackAddressChecker."); 86a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek } 87a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 88a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek return range; 89a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek} 90a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 91a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenekvoid StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R, 92a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek const Expr *RetE) { 93d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 94a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 95a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (!N) 969b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 979b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 98a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (!BT_returnstack) 99a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory"); 100a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 101a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Generate a report for this bug. 102a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::SmallString<512> buf; 103a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::raw_svector_ostream os(buf); 104a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceRange range = GenName(os, R, C.getSourceManager()); 105a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << " returned to caller"; 1069b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu RangedBugReport *report = new RangedBugReport(*BT_returnstack, os.str(), N); 1079b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu report->addRange(RetE->getSourceRange()); 1089b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (range.isValid()) 1099b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu report->addRange(range); 1109b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1119b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu C.EmitReport(report); 112a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman} 1139b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1149b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xuvoid StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C, 1159b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const ReturnStmt *RS) { 1169b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1179b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const Expr *RetE = RS->getRetValue(); 1189b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (!RetE) 1199b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 1209b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1219b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu SVal V = C.getState()->getSVal(RetE); 1229b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu const MemRegion *R = V.getAsRegion(); 1239b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1249b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (!R || !R->hasStackStorage()) 1259b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 1269b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu 1279b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu if (R->hasStackStorage()) { 1289b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu EmitStackError(C, R, RetE); 1299b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu return; 1309b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu } 1319b1468311d625ac8920adda5440ce8ffb1a5a5d2Zhongxing Xu} 1321622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu 133d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidisvoid StackAddrLeakChecker::evalEndPath(EndPathNodeBuilder &B, void *tag, 134d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis ExprEngine &Eng) { 1351622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode); 1361622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu const GRState *state = B.getState(); 137551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 138551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // Iterate over all bindings to global variables and see if it contains 139551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // a memory region in the stack space. 140551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek class CallBack : public StoreManager::BindingsHandler { 141551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek private: 142551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek const StackFrameContext *CurSFC; 143551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek public: 144a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V; 145551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 146551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek CallBack(const LocationContext *LCtx) 147a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek : CurSFC(LCtx->getCurrentStackFrame()) {} 148551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 149551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek bool HandleBinding(StoreManager &SMgr, Store store, 150551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek const MemRegion *region, SVal val) { 151551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 152551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!isa<GlobalsSpaceRegion>(region->getMemorySpace())) 153551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 154551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 155551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek const MemRegion *vR = val.getAsRegion(); 156551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!vR) 157551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 158551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 159551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (const StackSpaceRegion *SSR = 160551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) { 161551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // If the global variable holds a location in the current stack frame, 162551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // record the binding to emit a warning. 163a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (SSR->getStackFrame() == CurSFC) 164a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek V.push_back(std::make_pair(region, vR)); 1651622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu } 166551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 167551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return true; 1681622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu } 169551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek }; 170551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 171551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek CallBack cb(B.getPredecessor()->getLocationContext()); 172551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb); 173a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 174a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (cb.V.empty()) 175551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return; 176551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 177551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek // Generate an error node. 178551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor()); 179551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!N) 180551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek return; 181a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 182551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek if (!BT_stackleak) 183a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek BT_stackleak = 184a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek new BuiltinBug("Stack address stored into global variable", 185a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek "Stack address was saved into a global variable. " 186a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek "This is dangerous because the address will become " 187a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek "invalid after returning from the function"); 188551bd1f9191af0eecdc29764e34e01803c73ae31Ted Kremenek 189a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek for (unsigned i = 0, e = cb.V.size(); i != e; ++i) { 190a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek // Generate a report for this bug. 191a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::SmallString<512> buf; 192a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek llvm::raw_svector_ostream os(buf); 193a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek SourceRange range = GenName(os, cb.V[i].second, 194a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek Eng.getContext().getSourceManager()); 195a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << " is still referred to by the global variable '"; 196a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion()); 197a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek os << VR->getDecl()->getNameAsString() 198a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek << "' upon returning to the caller. This will be a dangling reference"; 199a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek RangedBugReport *report = new RangedBugReport(*BT_stackleak, os.str(), N); 200a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek if (range.isValid()) 201a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek report->addRange(range); 202a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek 203a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek Eng.getBugReporter().EmitReport(report); 204a8166156a6414ddd6a68514dc4f48e95d2259977Ted Kremenek } 2051622a547971cee50e386b4cdfe62ed1fcee1036dZhongxing Xu} 206