UndefCapturedBlockVarChecker.cpp revision 6f42b62b6194f53bcbc349f5d17388e1936535d7
194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=// 294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// 394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// The LLVM Compiler Infrastructure 494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// 594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// This file is distributed under the University of Illinois Open Source 694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// License. See LICENSE.TXT for details. 794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// 894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek//===----------------------------------------------------------------------===// 994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// 1094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// This checker detects blocks that capture uninitialized values. 1194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek// 1294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek//===----------------------------------------------------------------------===// 1394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 14265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis#include "ClangSACheckers.h" 15ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 16265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 17265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 199b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 208fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 2194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek#include "llvm/Support/raw_ostream.h" 2294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 2394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenekusing namespace clang; 249ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 2594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 2694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremeneknamespace { 2794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenekclass UndefCapturedBlockVarChecker 28ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis : public Checker< check::PostStmt<BlockExpr> > { 296f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith mutable OwningPtr<BugType> BT; 3094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 3194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenekpublic: 32265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; 3394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek}; 3494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek} // end anonymous namespace 3594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 3694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenekstatic const BlockDeclRefExpr *FindBlockDeclRefExpr(const Stmt *S, 3794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek const VarDecl *VD){ 3894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (const BlockDeclRefExpr *BR = dyn_cast<BlockDeclRefExpr>(S)) 3994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (BR->getDecl() == VD) 4094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek return BR; 4194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 4294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); 4394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek I!=E; ++I) 4494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (const Stmt *child = *I) { 4594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek const BlockDeclRefExpr *BR = FindBlockDeclRefExpr(child, VD); 4694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (BR) 4794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek return BR; 4894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek } 4994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 5094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek return NULL; 5194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek} 5294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 5394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenekvoid 54265c674f634e99e5df1135d764e21365351372daArgyrios KyrtzidisUndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, 55265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis CheckerContext &C) const { 56469a1eb996e1cb0be54f9b210f836afbddcbb2ccJohn McCall if (!BE->getBlockDecl()->hasCaptures()) 5794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek return; 5894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 598bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 6094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek const BlockDataRegion *R = 615eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek cast<BlockDataRegion>(state->getSVal(BE, 625eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek C.getLocationContext()).getAsRegion()); 6394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 6494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), 6594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek E = R->referenced_vars_end(); 6694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 6794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek for (; I != E; ++I) { 6894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek // This VarRegion is the region associated with the block; we need 6994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek // the one associated with the encompassing context. 7094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek const VarRegion *VR = *I; 7194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek const VarDecl *VD = VR->getDecl(); 7294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 7394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) 7494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek continue; 7594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 7694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek // Get the VarRegion associated with VD in the local stack frame. 7739ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks const LocationContext *LC = C.getLocationContext(); 78c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC); 7950bbc165b063155cc23c360deb7b865502e068e2Anna Zaks SVal VRVal = state->getSVal(VR); 8094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 8150bbc165b063155cc23c360deb7b865502e068e2Anna Zaks if (VRVal.isUndef()) 82d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateSink()) { 8394fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (!BT) 84265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis BT.reset(new BuiltinBug("uninitialized variable captured by block")); 8594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 8694fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek // Generate a bug report. 8794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek llvm::SmallString<128> buf; 8894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek llvm::raw_svector_ostream os(buf); 8994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 90937596fc25bba3ac7519e9ffff3e4fab2c97863eTed Kremenek os << "Variable '" << VD->getName() 91937596fc25bba3ac7519e9ffff3e4fab2c97863eTed Kremenek << "' is uninitialized when captured by block"; 9294fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek 93e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *R = new BugReport(*BT, os.str(), N); 9494fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD)) 9594fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek R->addRange(Ex->getSourceRange()); 9650bbc165b063155cc23c360deb7b865502e068e2Anna Zaks R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR)); 9794fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek // need location of block 9894fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek C.EmitReport(R); 9994fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek } 10094fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek } 10194fd0b8c88db9b1cd99457d3cd8cd333341dd39cTed Kremenek} 102265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis 103265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidisvoid ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) { 104265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis mgr.registerChecker<UndefCapturedBlockVarChecker>(); 105265c674f634e99e5df1135d764e21365351372daArgyrios Kyrtzidis} 106