MallocChecker.cpp revision 5d0ea6d62e076c776ddad028c4eb615783be1323
128c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--// 2fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// 3fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// The LLVM Compiler Infrastructure 4fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// 5fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// This file is distributed under the University of Illinois Open Source 6fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// License. See LICENSE.TXT for details. 7fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// 8fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar//===----------------------------------------------------------------------===// 9fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// 1028c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar// This file defines malloc/free checker, which checks for potential memory 1128c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar// leaks, double free, and use-after-free problems. 12fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar// 1385f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola//===----------------------------------------------------------------------===// 14fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "ClangSACheckers.h" 16fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar#include "clang/StaticAnalyzer/Core/Checker.h" 17fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18684c593d05db0bd277268fc9d8c05bce138c745aChris Lattner#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2032a006e606742b1c5401e49607e33717bb5441f0Rafael Espindola#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 21fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 220eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 2385f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola#include "llvm/ADT/ImmutableMap.h" 24fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbarusing namespace clang; 2515d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbarusing namespace ento; 2687392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbar 274f3e7aa154577c86791908e73a9fec075fdea0baChris Lattnernamespace { 2885f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola 29fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbarclass RefState { 3028c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped, 319643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar Relinquished } K; 3228c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar const Stmt *S; 33fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 3428c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbarpublic: 351aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar RefState(Kind k, const Stmt *s) : K(k), S(s) {} 361aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 371aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar bool isAllocated() const { return K == AllocateUnchecked; } 385d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner //bool isFailed() const { return K == AllocateFailed; } 395d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner bool isReleased() const { return K == Released; } 40fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar //bool isEscaped() const { return K == Escaped; } 419643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar //bool isRelinquished() const { return K == Relinquished; } 42fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 4328c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar bool operator==(const RefState &X) const { 449643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return K == X.K && S == X.S; 459643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 469643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 479643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar static RefState getAllocateUnchecked(const Stmt *s) { 48d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola return RefState(AllocateUnchecked, s); 49d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola } 5085f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola static RefState getAllocateFailed() { 51fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return RefState(AllocateFailed, 0); 52159f527cb269002de85e671023b9231a2c8792e9Dan Gohman } 539643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar static RefState getReleased(const Stmt *s) { return RefState(Released, s); } 54d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); } 55d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola static RefState getRelinquished(const Stmt *s) { 5685f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola return RefState(Relinquished, s); 57f230df9af4012f9510de664b6d62b128e26a5861Rafael Espindola } 58fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 599643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar void Profile(llvm::FoldingSetNodeID &ID) const { 609643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar ID.AddInteger(K); 61fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar ID.AddPointer(S); 6228c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar } 63fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar}; 649643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 6587392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbarclass RegionState {}; 6687392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbar 6787392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbarclass MallocChecker : public Checker<eval::Call, check::DeadSymbols, check::EndPath, check::PreStmt<ReturnStmt>, check::Location, 688cb9a3b13f3226b7e741768b69d26ecd6b5231f1Chris Lattner check::Bind, eval::Assume> { 6987392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbar mutable llvm::OwningPtr<BuiltinBug> BT_DoubleFree; 7087392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbar mutable llvm::OwningPtr<BuiltinBug> BT_Leak; 7187392fde1f261fea161b48886fafbedddb18dcceDaniel Dunbar mutable llvm::OwningPtr<BuiltinBug> BT_UseFree; 729643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar mutable llvm::OwningPtr<BuiltinBug> BT_UseRelinquished; 739643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar mutable llvm::OwningPtr<BuiltinBug> BT_BadFree; 749643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc; 75fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 76fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbarpublic: 7715d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbar MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {} 78f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar 79f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar bool evalCall(const CallExpr *CE, CheckerContext &C) const; 80f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 81fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const; 82d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; 83d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola const ProgramState *evalAssume(const ProgramState *state, SVal Cond, 84d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola bool Assumption) const; 8585f2ecc697a8ca6c8cf08093054cbbb9d2060ccfRafael Espindola void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; 86d076482ab7e672d1d65a43809695e8d0d3995203Rafael Espindola void checkBind(SVal location, SVal val, CheckerContext &C) const; 87fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 8815d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbarprivate: 891aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar static void MallocMem(CheckerContext &C, const CallExpr *CE); 9015d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbar static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, 9115d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbar const OwnershipAttr* Att); 92f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE, 9315d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbar const Expr *SizeEx, SVal Init, 9433a38a1b5a35acd15c867193bc2175f3d4e7b83dRafael Espindola const ProgramState *state) { 9515d170709608e2f1efcada74c297c10c8c71fdcfDaniel Dunbar return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state); 960eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar } 970eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE, 980eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar SVal SizeEx, SVal Init, 990eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar const ProgramState *state); 1000eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar 1010eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar void FreeMem(CheckerContext &C, const CallExpr *CE) const; 1029643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar void FreeMemAttr(CheckerContext &C, const CallExpr *CE, 1039643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const OwnershipAttr* Att) const; 10428c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar const ProgramState *FreeMemAux(CheckerContext &C, const CallExpr *CE, 105fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const ProgramState *state, unsigned Num, bool Hold) const; 106a0e36d55c495b3325805c659ac365b5faea84e34Daniel Dunbar 1078cb9a3b13f3226b7e741768b69d26ecd6b5231f1Chris Lattner void ReallocMem(CheckerContext &C, const CallExpr *CE) const; 1088cb9a3b13f3226b7e741768b69d26ecd6b5231f1Chris Lattner static void CallocMem(CheckerContext &C, const CallExpr *CE); 1098cb9a3b13f3226b7e741768b69d26ecd6b5231f1Chris Lattner 1108cb9a3b13f3226b7e741768b69d26ecd6b5231f1Chris Lattner static bool SummarizeValue(raw_ostream &os, SVal V); 111fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); 11228c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const; 11328c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar}; 114fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar} // end anonymous namespace 115fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 116159f527cb269002de85e671023b9231a2c8792e9Dan Gohmantypedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy; 11728c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar 1189643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarnamespace clang { 1199643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarnamespace ento { 1209643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar template <> 1219643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar struct ProgramStateTrait<RegionState> 1229643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar : public ProgramStatePartialTrait<RegionStateTy> { 1239643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar static void *GDMIndex() { static int x; return &x; } 1249643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar }; 1259643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar} 1269643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar} 1279643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 1289643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarbool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 129fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const ProgramState *state = C.getState(); 130fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const Expr *Callee = CE->getCallee(); 1319643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar SVal L = state->getSVal(Callee); 1329643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 1339643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const FunctionDecl *FD = L.getAsFunctionDecl(); 1349643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (!FD) 135fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return false; 13628c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar 137fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar ASTContext &Ctx = C.getASTContext(); 138fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar if (!II_malloc) 13928c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar II_malloc = &Ctx.Idents.get("malloc"); 1401aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar if (!II_free) 1411aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar II_free = &Ctx.Idents.get("free"); 1421aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar if (!II_realloc) 1431aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar II_realloc = &Ctx.Idents.get("realloc"); 1441aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar if (!II_calloc) 14528c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar II_calloc = &Ctx.Idents.get("calloc"); 1464e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 1474e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar if (FD->getIdentifier() == II_malloc) { 1484e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar MallocMem(C, CE); 1494e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar return true; 1504e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar } 1514e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 1524e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar if (FD->getIdentifier() == II_free) { 1534e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar FreeMem(C, CE); 1544e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar return true; 1554e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar } 1564e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 157a0a2f8734cdfc19d44201b791a969bcdda96bb70Rafael Espindola if (FD->getIdentifier() == II_realloc) { 1584e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar ReallocMem(C, CE); 1594e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar return true; 160b4d1721eff7b43577e5f2e53f885973fb6c43683Rafael Espindola } 161a264f72d3fb9dec1427480fcf17ef3c746ea723aRafael Espindola 16218c1021ec108722506125926087b1e5fcfb28046Rafael Espindola if (FD->getIdentifier() == II_calloc) { 1630cf15d61b7e3bf53f5a99f58ada37b93bc039559Rafael Espindola CallocMem(C, CE); 1646135a96792ca05f6366e5dbaee6208e84589c47fChris Lattner return true; 1652c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach } 1662c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach 1672c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach // Check all the attributes, if there are any. 1682c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach // There can be multiple of these attributes. 1692c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach bool rv = false; 1702c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach if (FD->hasAttrs()) { 1712c4d5125c708bb35140fc2a40b02beb1add101dbJim Grosbach for (specific_attr_iterator<OwnershipAttr> 172c67b1a3a76ea6ff642d30610cf63595ccb661e6bBob Wilson i = FD->specific_attr_begin<OwnershipAttr>(), 1731e61e69d401045c54b15815f15a0fdb3ca56a9b5Chris Lattner e = FD->specific_attr_end<OwnershipAttr>(); 174a1000742d28f33dd8dd9858e64282e7749c0bd64Roman Divacky i != e; ++i) { 175a1000742d28f33dd8dd9858e64282e7749c0bd64Roman Divacky switch ((*i)->getOwnKind()) { 176a1000742d28f33dd8dd9858e64282e7749c0bd64Roman Divacky case OwnershipAttr::Returns: { 1773507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes MallocMemReturnsAttr(C, CE, *i); 1783507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes rv = true; 1793507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes break; 1803507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes } 181e3d3572e282733bd7aa5ac14115ed0804174e426Bruno Cardoso Lopes case OwnershipAttr::Takes: 1823507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes case OwnershipAttr::Holds: { 1833507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes FreeMemAttr(C, CE, *i); 1843507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes rv = true; 1853507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes break; 1863faac0a78c7a70d3dcd2af102a132bb9da2d639cAkira Hatanaka } 1873faac0a78c7a70d3dcd2af102a132bb9da2d639cAkira Hatanaka default: 1883faac0a78c7a70d3dcd2af102a132bb9da2d639cAkira Hatanaka break; 1893507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes } 1903507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes } 1913507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes } 1923507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes return rv; 1933507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes} 1943507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes 1953507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopesvoid MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { 1963507d24547ce668c9a50c72b6748c0a303e295c1Bruno Cardoso Lopes const ProgramState *state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), 1974e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar C.getState()); 1984e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar C.addTransition(state); 1994e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar} 2004e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 2019643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarvoid MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, 202fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const OwnershipAttr* Att) { 2034e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar if (Att->getModule() != "malloc") 2044e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar return; 2054e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 2064e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 20799b4237c1647156f0e1d3d7e03efdab23ed79778Rafael Espindola if (I != E) { 20899b4237c1647156f0e1d3d7e03efdab23ed79778Rafael Espindola const ProgramState *state = 20999b4237c1647156f0e1d3d7e03efdab23ed79778Rafael Espindola MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); 210fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar C.addTransition(state); 2119643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return; 2129643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 2139643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const ProgramState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), 2149643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar C.getState()); 2154e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar C.addTransition(state); 2164e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar} 2174e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 2184e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbarconst ProgramState *MallocChecker::MallocMemAux(CheckerContext &C, 2194e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar const CallExpr *CE, 2204e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar SVal Size, SVal Init, 2214e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar const ProgramState *state) { 2224e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar unsigned Count = C.getCurrentBlockCount(); 223c67b1a3a76ea6ff642d30610cf63595ccb661e6bBob Wilson SValBuilder &svalBuilder = C.getSValBuilder(); 2249643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2259643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Set the return value. 2269643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE, CE->getType(), Count); 2279643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar state = state->BindExpr(CE, retVal); 2289643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2299643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Fill the region with the initialization value. 2304e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar state = state->bindDefault(retVal, Init); 2314e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 2324e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar // Set the region's extent equal to the Size parameter. 2334e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar const SymbolicRegion *R = cast<SymbolicRegion>(retVal.getAsRegion()); 2344e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 2354e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size); 2364e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar DefinedOrUnknownSVal extentMatchesSize = 2374e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar svalBuilder.evalEQ(state, Extent, DefinedSize); 2384e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar 2394e815f8a8cae6c846cdca52420046cab902865deDaniel Dunbar state = state->assume(extentMatchesSize, true); 2409643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar assert(state); 2419643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2429643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar SymbolRef Sym = retVal.getAsLocSymbol(); 2439643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar assert(Sym); 244fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 24528c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar // Set the symbol's state to Allocated. 246fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE)); 247fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar} 24828c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar 24928c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbarvoid MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const { 250fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const ProgramState *state = FreeMemAux(C, CE, C.getState(), 0, false); 251fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 2521aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar if (state) 2531aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar C.addTransition(state); 2541aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar} 2551aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 256fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbarvoid MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, 257fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const OwnershipAttr* Att) const { 258fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar if (Att->getModule() != "malloc") 259fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return; 2609643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 261fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 2629643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar I != E; ++I) { 26328c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar const ProgramState *state = FreeMemAux(C, CE, C.getState(), *I, 2649643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar Att->getOwnKind() == OwnershipAttr::Holds); 2659643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (state) 2669643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar C.addTransition(state); 2679643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 2689643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar} 2699643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2709643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarconst ProgramState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE, 2719643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const ProgramState *state, unsigned Num, 2729643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar bool Hold) const { 2739643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const Expr *ArgExpr = CE->getArg(Num); 2749643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar SVal ArgVal = state->getSVal(ArgExpr); 2759643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2769643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal); 2779643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2789643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Check for null dereferences. 279fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar if (!isa<Loc>(location)) 2809643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return state; 2819643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 2829643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // FIXME: Technically using 'Assume' here can result in a path 2839643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // bifurcation. In such cases we need to return two states, not just one. 2849643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const ProgramState *notNullState, *nullState; 2859643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar llvm::tie(notNullState, nullState) = state->assume(location); 2869643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 287fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar // The explicit NULL case, no operation is performed. 2889643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (nullState && !notNullState) 289fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return nullState; 290fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 2919643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar assert(notNullState); 2929643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 293fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar // Unknown values could easily be okay 2949643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Undefined values are handled elsewhere 2959643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (ArgVal.isUnknownOrUndef()) 2969643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return notNullState; 2979643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 298fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const MemRegion *R = ArgVal.getAsRegion(); 29928c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar 300fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar // Nonlocs can't be freed, of course. 301fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar // Non-region locations (labels and fixed addresses) also shouldn't be freed. 30228c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar if (!R) { 30328c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 304fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return NULL; 305fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar } 3061aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 3071aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar R = R->StripCasts(); 308036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman 3091aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar // Blocks might show up as heap data, but should not be free()d 310036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman if (isa<BlockDataRegion>(R)) { 311036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 312036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman return NULL; 313036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman } 3141aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 3151aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar const MemSpaceRegion *MS = R->getMemorySpace(); 316036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman 317036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman // Parameters, locals, statics, and globals shouldn't be freed. 318036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) { 319036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman // FIXME: at the time this code was written, malloc() regions were 320036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman // represented by conjured symbols, which are all in UnknownSpaceRegion. 3211aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar // This means that there isn't actually anything from HeapSpaceRegion 3221aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar // that should be freed, even though we allow it here. 3231aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar // Of course, free() can work on memory allocated outside the current 324036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman // function, so UnknownSpaceRegion is always a possibility. 325036c130e90eb5c93b0dc0a70ad07b9343623c2a8Dan Gohman // False negatives are better than false positives. 3261aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 3271aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 328fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar return NULL; 329fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar } 330fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 331fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R); 3329643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Various cases could lead to non-symbol values here. 333fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar // For now, ignore them. 3349643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (!SR) 33528c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar return notNullState; 3369643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3379643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar SymbolRef Sym = SR->getSymbol(); 3389643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const RefState *RS = state->get<RegionState>(Sym); 3399643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3409643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // If the symbol has not been tracked, return. This is possible when free() is 3419643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // called on a pointer that does not get its pointee directly from malloc(). 3429643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Full support of this requires inter-procedural analysis. 3439643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (!RS) 3449643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return notNullState; 3459643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3469643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Check double free. 3479643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (RS->isReleased()) { 3489643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (ExplodedNode *N = C.generateSink()) { 3499643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (!BT_DoubleFree) 3509643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar BT_DoubleFree.reset( 3519643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar new BuiltinBug("Double free", 3529643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar "Try to free a memory block that has been released")); 3539643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // FIXME: should find where it's freed last time. 3549643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar BugReport *R = new BugReport(*BT_DoubleFree, 3559643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar BT_DoubleFree->getDescription(), N); 3569643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar C.EmitReport(R); 3579643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 3589643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return NULL; 3599643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 3609643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3619643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // Normal free. 3629643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (Hold) 3639643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE)); 3649643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return notNullState->set<RegionState>(Sym, RefState::getReleased(CE)); 3659643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar} 3669643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3679643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarbool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { 3689643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V)) 3699643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "an integer (" << IntVal->getValue() << ")"; 370fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V)) 3719643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "a constant address (" << ConstAddr->getValue() << ")"; 3729643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V)) 3739643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of the label '" << Label->getLabel()->getName() << "'"; 3749643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar else 3759643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return false; 3769643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3779643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 3789643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar} 3799643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 3809643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbarbool MallocChecker::SummarizeRegion(raw_ostream &os, 3819643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const MemRegion *MR) { 3829643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar switch (MR->getKind()) { 3839643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::FunctionTextRegionKind: { 3849643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 3859643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (FD) 3869643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of the function '" << FD << "'"; 3879643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar else 3889643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of a function"; 3899643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 3909643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 3919643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::BlockTextRegionKind: 3929643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "block text"; 3939643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 3949643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::BlockDataRegionKind: 3959643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar // FIXME: where the block came from? 3969643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "a block"; 3979643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 3989643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar default: { 3999643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const MemSpaceRegion *MS = MR->getMemorySpace(); 4009643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 4019643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar switch (MS->getKind()) { 4029643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::StackLocalsSpaceRegionKind: { 4039643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const VarRegion *VR = dyn_cast<VarRegion>(MR); 4049643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const VarDecl *VD; 4059643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (VR) 4069643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar VD = VR->getDecl(); 4079643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar else 4089643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar VD = NULL; 4099643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar 4109643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (VD) 4119643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of the local variable '" << VD->getName() << "'"; 4129643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar else 4139643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of a local stack variable"; 4149643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 4159643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 4169643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::StackArgumentsSpaceRegionKind: { 4179643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const VarRegion *VR = dyn_cast<VarRegion>(MR); 4189643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const VarDecl *VD; 419fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar if (VR) 4209643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar VD = VR->getDecl(); 421fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar else 422fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar VD = NULL; 4231aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar 4249643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar if (VD) 4251aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar os << "the address of the parameter '" << VD->getName() << "'"; 4261aa14aac4198bca0f44e4adad42bf6238cbf9757Daniel Dunbar else 4279643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar os << "the address of a parameter"; 4289643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar return true; 4299643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar } 430fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar case MemRegion::NonStaticGlobalSpaceRegionKind: 4319643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar case MemRegion::StaticGlobalSpaceRegionKind: { 4329643ac55142d40da404caa8e5fedfef2cd7b4afcDaniel Dunbar const VarRegion *VR = dyn_cast<VarRegion>(MR); 433fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar const VarDecl *VD; 43428c251b54b0b311749f07babe0f6909e71e877bcDaniel Dunbar if (VR) 435fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar VD = VR->getDecl(); 436fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar else 4375d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner VD = NULL; 4385d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner 4395d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner if (VD) { 4405d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner if (VD->isStaticLocal()) 4415d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner os << "the address of the static variable '" << VD->getName() << "'"; 4425d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner else 443df9c4380ee7e60c1de5cae32685b113170b1faa2Chris Lattner os << "the address of the global variable '" << VD->getName() << "'"; 4445d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner } else 4455d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner os << "the address of a global variable"; 446e3e7a369f20af66a96830d8bfe52668c9e2e1fa1Chris Lattner return true; 4475d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner } 448a0e36d55c495b3325805c659ac365b5faea84e34Daniel Dunbar default: 4495d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner return false; 450f82f4490b130eca55b08d605456a4ceacccf288aDaniel Dunbar } 451a0e36d55c495b3325805c659ac365b5faea84e34Daniel Dunbar } 4527597212abced110723f2fee985a7d60557c092ecEvan Cheng } 4530eab5c4d85b4c4bb161bcdd959aa58a6f54415ccDaniel Dunbar} 4545d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner 4555d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattnervoid MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, 4565d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner SourceRange range) const { 4575d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner if (ExplodedNode *N = C.generateSink()) { 4585d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner if (!BT_BadFree) 4595d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner BT_BadFree.reset(new BuiltinBug("Bad free")); 4605d917a8952c09a345180ec36f0df4ee5dd5eddeaChris Lattner 461fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar llvm::SmallString<100> buf; 462fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar llvm::raw_svector_ostream os(buf); 463fc6877aec9826fa830204d49eba7fac7412b841eDaniel Dunbar 464 const MemRegion *MR = ArgVal.getAsRegion(); 465 if (MR) { 466 while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) 467 MR = ER->getSuperRegion(); 468 469 // Special case for alloca() 470 if (isa<AllocaRegion>(MR)) 471 os << "Argument to free() was allocated by alloca(), not malloc()"; 472 else { 473 os << "Argument to free() is "; 474 if (SummarizeRegion(os, MR)) 475 os << ", which is not memory allocated by malloc()"; 476 else 477 os << "not memory allocated by malloc()"; 478 } 479 } else { 480 os << "Argument to free() is "; 481 if (SummarizeValue(os, ArgVal)) 482 os << ", which is not memory allocated by malloc()"; 483 else 484 os << "not memory allocated by malloc()"; 485 } 486 487 BugReport *R = new BugReport(*BT_BadFree, os.str(), N); 488 R->addRange(range); 489 C.EmitReport(R); 490 } 491} 492 493void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { 494 const ProgramState *state = C.getState(); 495 const Expr *arg0Expr = CE->getArg(0); 496 DefinedOrUnknownSVal arg0Val 497 = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr)); 498 499 SValBuilder &svalBuilder = C.getSValBuilder(); 500 501 DefinedOrUnknownSVal PtrEQ = 502 svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull()); 503 504 // Get the size argument. If there is no size arg then give up. 505 const Expr *Arg1 = CE->getArg(1); 506 if (!Arg1) 507 return; 508 509 // Get the value of the size argument. 510 DefinedOrUnknownSVal Arg1Val = 511 cast<DefinedOrUnknownSVal>(state->getSVal(Arg1)); 512 513 // Compare the size argument to 0. 514 DefinedOrUnknownSVal SizeZero = 515 svalBuilder.evalEQ(state, Arg1Val, 516 svalBuilder.makeIntValWithPtrWidth(0, false)); 517 518 // If the ptr is NULL and the size is not 0, the call is equivalent to 519 // malloc(size). 520 const ProgramState *stateEqual = state->assume(PtrEQ, true); 521 if (stateEqual && state->assume(SizeZero, false)) { 522 // Hack: set the NULL symbolic region to released to suppress false warning. 523 // In the future we should add more states for allocated regions, e.g., 524 // CheckedNull, CheckedNonNull. 525 526 SymbolRef Sym = arg0Val.getAsLocSymbol(); 527 if (Sym) 528 stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE)); 529 530 const ProgramState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1), 531 UndefinedVal(), stateEqual); 532 C.addTransition(stateMalloc); 533 } 534 535 if (const ProgramState *stateNotEqual = state->assume(PtrEQ, false)) { 536 // If the size is 0, free the memory. 537 if (const ProgramState *stateSizeZero = stateNotEqual->assume(SizeZero, true)) 538 if (const ProgramState *stateFree = 539 FreeMemAux(C, CE, stateSizeZero, 0, false)) { 540 541 // Bind the return value to NULL because it is now free. 542 C.addTransition(stateFree->BindExpr(CE, svalBuilder.makeNull(), true)); 543 } 544 if (const ProgramState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false)) 545 if (const ProgramState *stateFree = FreeMemAux(C, CE, stateSizeNotZero, 546 0, false)) { 547 // FIXME: We should copy the content of the original buffer. 548 const ProgramState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 549 UnknownVal(), stateFree); 550 C.addTransition(stateRealloc); 551 } 552 } 553} 554 555void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { 556 const ProgramState *state = C.getState(); 557 SValBuilder &svalBuilder = C.getSValBuilder(); 558 559 SVal count = state->getSVal(CE->getArg(0)); 560 SVal elementSize = state->getSVal(CE->getArg(1)); 561 SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize, 562 svalBuilder.getContext().getSizeType()); 563 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); 564 565 C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state)); 566} 567 568void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, 569 CheckerContext &C) const 570{ 571 if (!SymReaper.hasDeadSymbols()) 572 return; 573 574 const ProgramState *state = C.getState(); 575 RegionStateTy RS = state->get<RegionState>(); 576 RegionStateTy::Factory &F = state->get_context<RegionState>(); 577 578 bool generateReport = false; 579 580 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 581 if (SymReaper.isDead(I->first)) { 582 if (I->second.isAllocated()) 583 generateReport = true; 584 585 // Remove the dead symbol from the map. 586 RS = F.remove(RS, I->first); 587 588 } 589 } 590 591 ExplodedNode *N = C.generateNode(state->set<RegionState>(RS)); 592 593 // FIXME: This does not handle when we have multiple leaks at a single 594 // place. 595 if (N && generateReport) { 596 if (!BT_Leak) 597 BT_Leak.reset(new BuiltinBug("Memory leak", 598 "Allocated memory never released. Potential memory leak.")); 599 // FIXME: where it is allocated. 600 BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); 601 C.EmitReport(R); 602 } 603} 604 605void MallocChecker::checkEndPath(EndOfFunctionNodeBuilder &B, 606 ExprEngine &Eng) const { 607 const ProgramState *state = B.getState(); 608 RegionStateTy M = state->get<RegionState>(); 609 610 for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { 611 RefState RS = I->second; 612 if (RS.isAllocated()) { 613 ExplodedNode *N = B.generateNode(state); 614 if (N) { 615 if (!BT_Leak) 616 BT_Leak.reset(new BuiltinBug("Memory leak", 617 "Allocated memory never released. Potential memory leak.")); 618 BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); 619 Eng.getBugReporter().EmitReport(R); 620 } 621 } 622 } 623} 624 625void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { 626 const Expr *retExpr = S->getRetValue(); 627 if (!retExpr) 628 return; 629 630 const ProgramState *state = C.getState(); 631 632 SymbolRef Sym = state->getSVal(retExpr).getAsSymbol(); 633 if (!Sym) 634 return; 635 636 const RefState *RS = state->get<RegionState>(Sym); 637 if (!RS) 638 return; 639 640 // FIXME: check other cases. 641 if (RS->isAllocated()) 642 state = state->set<RegionState>(Sym, RefState::getEscaped(S)); 643 644 C.addTransition(state); 645} 646 647const ProgramState *MallocChecker::evalAssume(const ProgramState *state, SVal Cond, 648 bool Assumption) const { 649 // If a symblic region is assumed to NULL, set its state to AllocateFailed. 650 // FIXME: should also check symbols assumed to non-null. 651 652 RegionStateTy RS = state->get<RegionState>(); 653 654 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 655 // If the symbol is assumed to NULL, this will return an APSInt*. 656 if (state->getSymVal(I.getKey())) 657 state = state->set<RegionState>(I.getKey(),RefState::getAllocateFailed()); 658 } 659 660 return state; 661} 662 663// Check if the location is a freed symbolic region. 664void MallocChecker::checkLocation(SVal l, bool isLoad,CheckerContext &C) const { 665 SymbolRef Sym = l.getLocSymbolInBase(); 666 if (Sym) { 667 const RefState *RS = C.getState()->get<RegionState>(Sym); 668 if (RS && RS->isReleased()) { 669 if (ExplodedNode *N = C.generateNode()) { 670 if (!BT_UseFree) 671 BT_UseFree.reset(new BuiltinBug("Use dynamically allocated memory " 672 "after it is freed.")); 673 674 BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(), 675 N); 676 C.EmitReport(R); 677 } 678 } 679 } 680} 681 682void MallocChecker::checkBind(SVal location, SVal val,CheckerContext &C) const { 683 // The PreVisitBind implements the same algorithm as already used by the 684 // Objective C ownership checker: if the pointer escaped from this scope by 685 // assignment, let it go. However, assigning to fields of a stack-storage 686 // structure does not transfer ownership. 687 688 const ProgramState *state = C.getState(); 689 DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location); 690 691 // Check for null dereferences. 692 if (!isa<Loc>(l)) 693 return; 694 695 // Before checking if the state is null, check if 'val' has a RefState. 696 // Only then should we check for null and bifurcate the state. 697 SymbolRef Sym = val.getLocSymbolInBase(); 698 if (Sym) { 699 if (const RefState *RS = state->get<RegionState>(Sym)) { 700 // If ptr is NULL, no operation is performed. 701 const ProgramState *notNullState, *nullState; 702 llvm::tie(notNullState, nullState) = state->assume(l); 703 704 // Generate a transition for 'nullState' to record the assumption 705 // that the state was null. 706 if (nullState) 707 C.addTransition(nullState); 708 709 if (!notNullState) 710 return; 711 712 if (RS->isAllocated()) { 713 // Something we presently own is being assigned somewhere. 714 const MemRegion *AR = location.getAsRegion(); 715 if (!AR) 716 return; 717 AR = AR->StripCasts()->getBaseRegion(); 718 do { 719 // If it is on the stack, we still own it. 720 if (AR->hasStackNonParametersStorage()) 721 break; 722 723 // If the state can't represent this binding, we still own it. 724 if (notNullState == (notNullState->bindLoc(cast<Loc>(location), 725 UnknownVal()))) 726 break; 727 728 // We no longer own this pointer. 729 notNullState = 730 notNullState->set<RegionState>(Sym, 731 RefState::getRelinquished(C.getStmt())); 732 } 733 while (false); 734 } 735 C.addTransition(notNullState); 736 } 737 } 738} 739 740void ento::registerMallocChecker(CheckerManager &mgr) { 741 mgr.registerChecker<MallocChecker>(); 742} 743