1218887Sdim//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This file defines malloc/free checker, which checks for potential memory 11218887Sdim// leaks, double free, and use-after-free problems. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15221345Sdim#include "ClangSACheckers.h" 16234353Sdim#include "InterCheckerAPI.h" 17249423Sdim#include "clang/AST/Attr.h" 18249423Sdim#include "clang/Basic/SourceManager.h" 19249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 21221345Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 22249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 23221345Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 24226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 25226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 26218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 27218887Sdim#include "llvm/ADT/ImmutableMap.h" 28249423Sdim#include "llvm/ADT/STLExtras.h" 29234353Sdim#include "llvm/ADT/SmallString.h" 30243830Sdim#include "llvm/ADT/StringExtras.h" 31234353Sdim#include <climits> 32234353Sdim 33218887Sdimusing namespace clang; 34218887Sdimusing namespace ento; 35218887Sdim 36218887Sdimnamespace { 37218887Sdim 38249423Sdim// Used to check correspondence between allocators and deallocators. 39249423Sdimenum AllocationFamily { 40249423Sdim AF_None, 41249423Sdim AF_Malloc, 42249423Sdim AF_CXXNew, 43249423Sdim AF_CXXNewArray 44249423Sdim}; 45249423Sdim 46218887Sdimclass RefState { 47239462Sdim enum Kind { // Reference to allocated memory. 48239462Sdim Allocated, 49239462Sdim // Reference to released/freed memory. 50239462Sdim Released, 51239462Sdim // The responsibility for freeing resources has transfered from 52239462Sdim // this reference. A relinquished symbol should not be freed. 53251662Sdim Relinquished, 54251662Sdim // We are no longer guaranteed to have observed all manipulations 55251662Sdim // of this pointer/memory. For example, it could have been 56251662Sdim // passed as a parameter to an opaque function. 57251662Sdim Escaped 58251662Sdim }; 59249423Sdim 60218887Sdim const Stmt *S; 61249423Sdim unsigned K : 2; // Kind enum, but stored as a bitfield. 62249423Sdim unsigned Family : 30; // Rest of 32-bit word, currently just an allocation 63249423Sdim // family. 64218887Sdim 65249423Sdim RefState(Kind k, const Stmt *s, unsigned family) 66251662Sdim : S(s), K(k), Family(family) { 67251662Sdim assert(family != AF_None); 68251662Sdim } 69218887Sdimpublic: 70239462Sdim bool isAllocated() const { return K == Allocated; } 71218887Sdim bool isReleased() const { return K == Released; } 72239462Sdim bool isRelinquished() const { return K == Relinquished; } 73251662Sdim bool isEscaped() const { return K == Escaped; } 74251662Sdim AllocationFamily getAllocationFamily() const { 75249423Sdim return (AllocationFamily)Family; 76249423Sdim } 77234353Sdim const Stmt *getStmt() const { return S; } 78234353Sdim 79218887Sdim bool operator==(const RefState &X) const { 80249423Sdim return K == X.K && S == X.S && Family == X.Family; 81218887Sdim } 82218887Sdim 83249423Sdim static RefState getAllocated(unsigned family, const Stmt *s) { 84249423Sdim return RefState(Allocated, s, family); 85218887Sdim } 86249423Sdim static RefState getReleased(unsigned family, const Stmt *s) { 87249423Sdim return RefState(Released, s, family); 88218887Sdim } 89249423Sdim static RefState getRelinquished(unsigned family, const Stmt *s) { 90249423Sdim return RefState(Relinquished, s, family); 91249423Sdim } 92251662Sdim static RefState getEscaped(const RefState *RS) { 93251662Sdim return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily()); 94251662Sdim } 95218887Sdim 96218887Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 97218887Sdim ID.AddInteger(K); 98218887Sdim ID.AddPointer(S); 99249423Sdim ID.AddInteger(Family); 100218887Sdim } 101249423Sdim 102249423Sdim void dump(raw_ostream &OS) const { 103263508Sdim static const char *const Table[] = { 104249423Sdim "Allocated", 105249423Sdim "Released", 106249423Sdim "Relinquished" 107249423Sdim }; 108249423Sdim OS << Table[(unsigned) K]; 109249423Sdim } 110249423Sdim 111249423Sdim LLVM_ATTRIBUTE_USED void dump() const { 112249423Sdim dump(llvm::errs()); 113249423Sdim } 114218887Sdim}; 115218887Sdim 116243830Sdimenum ReallocPairKind { 117243830Sdim RPToBeFreedAfterFailure, 118243830Sdim // The symbol has been freed when reallocation failed. 119243830Sdim RPIsFreeOnFailure, 120243830Sdim // The symbol does not need to be freed after reallocation fails. 121243830Sdim RPDoNotTrackAfterFailure 122243830Sdim}; 123243830Sdim 124243830Sdim/// \class ReallocPair 125243830Sdim/// \brief Stores information about the symbol being reallocated by a call to 126243830Sdim/// 'realloc' to allow modeling failed reallocation later in the path. 127234353Sdimstruct ReallocPair { 128243830Sdim // \brief The symbol which realloc reallocated. 129234353Sdim SymbolRef ReallocatedSym; 130243830Sdim ReallocPairKind Kind; 131243830Sdim 132243830Sdim ReallocPair(SymbolRef S, ReallocPairKind K) : 133243830Sdim ReallocatedSym(S), Kind(K) {} 134234353Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 135243830Sdim ID.AddInteger(Kind); 136234353Sdim ID.AddPointer(ReallocatedSym); 137234353Sdim } 138234353Sdim bool operator==(const ReallocPair &X) const { 139234353Sdim return ReallocatedSym == X.ReallocatedSym && 140243830Sdim Kind == X.Kind; 141234353Sdim } 142234353Sdim}; 143218887Sdim 144249423Sdimtypedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo; 145218887Sdim 146234353Sdimclass MallocChecker : public Checker<check::DeadSymbols, 147249423Sdim check::PointerEscape, 148249423Sdim check::ConstPointerEscape, 149234353Sdim check::PreStmt<ReturnStmt>, 150251662Sdim check::PreCall, 151234353Sdim check::PostStmt<CallExpr>, 152249423Sdim check::PostStmt<CXXNewExpr>, 153249423Sdim check::PreStmt<CXXDeleteExpr>, 154234353Sdim check::PostStmt<BlockExpr>, 155243830Sdim check::PostObjCMessage, 156234353Sdim check::Location, 157249423Sdim eval::Assume> 158234353Sdim{ 159234353Sdim mutable OwningPtr<BugType> BT_DoubleFree; 160234353Sdim mutable OwningPtr<BugType> BT_Leak; 161234353Sdim mutable OwningPtr<BugType> BT_UseFree; 162234353Sdim mutable OwningPtr<BugType> BT_BadFree; 163249423Sdim mutable OwningPtr<BugType> BT_MismatchedDealloc; 164249423Sdim mutable OwningPtr<BugType> BT_OffsetFree; 165234353Sdim mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc, 166234353Sdim *II_valloc, *II_reallocf, *II_strndup, *II_strdup; 167234353Sdim 168218887Sdimpublic: 169234353Sdim MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0), 170234353Sdim II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {} 171218887Sdim 172234353Sdim /// In pessimistic mode, the checker assumes that it does not know which 173234353Sdim /// functions might free the memory. 174234353Sdim struct ChecksFilter { 175234353Sdim DefaultBool CMallocPessimistic; 176234353Sdim DefaultBool CMallocOptimistic; 177249423Sdim DefaultBool CNewDeleteChecker; 178251662Sdim DefaultBool CNewDeleteLeaksChecker; 179249423Sdim DefaultBool CMismatchedDeallocatorChecker; 180234353Sdim }; 181234353Sdim 182234353Sdim ChecksFilter Filter; 183234353Sdim 184251662Sdim void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 185234353Sdim void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; 186249423Sdim void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; 187249423Sdim void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const; 188243830Sdim void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const; 189234353Sdim void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; 190221345Sdim void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 191221345Sdim void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; 192234353Sdim ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, 193221345Sdim bool Assumption) const; 194226633Sdim void checkLocation(SVal l, bool isLoad, const Stmt *S, 195226633Sdim CheckerContext &C) const; 196221345Sdim 197249423Sdim ProgramStateRef checkPointerEscape(ProgramStateRef State, 198249423Sdim const InvalidatedSymbols &Escaped, 199249423Sdim const CallEvent *Call, 200249423Sdim PointerEscapeKind Kind) const; 201249423Sdim ProgramStateRef checkConstPointerEscape(ProgramStateRef State, 202249423Sdim const InvalidatedSymbols &Escaped, 203249423Sdim const CallEvent *Call, 204249423Sdim PointerEscapeKind Kind) const; 205249423Sdim 206239462Sdim void printState(raw_ostream &Out, ProgramStateRef State, 207239462Sdim const char *NL, const char *Sep) const; 208239462Sdim 209218887Sdimprivate: 210234353Sdim void initIdentifierInfo(ASTContext &C) const; 211234353Sdim 212249423Sdim /// \brief Determine family of a deallocation expression. 213249423Sdim AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const; 214249423Sdim 215249423Sdim /// \brief Print names of allocators and deallocators. 216249423Sdim /// 217249423Sdim /// \returns true on success. 218249423Sdim bool printAllocDeallocName(raw_ostream &os, CheckerContext &C, 219249423Sdim const Expr *E) const; 220249423Sdim 221249423Sdim /// \brief Print expected name of an allocator based on the deallocator's 222249423Sdim /// family derived from the DeallocExpr. 223249423Sdim void printExpectedAllocName(raw_ostream &os, CheckerContext &C, 224249423Sdim const Expr *DeallocExpr) const; 225249423Sdim /// \brief Print expected name of a deallocator based on the allocator's 226249423Sdim /// family. 227249423Sdim void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) const; 228249423Sdim 229249423Sdim ///@{ 230234353Sdim /// Check if this is one of the functions which can allocate/reallocate memory 231234353Sdim /// pointed to by one of its arguments. 232234353Sdim bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const; 233239462Sdim bool isFreeFunction(const FunctionDecl *FD, ASTContext &C) const; 234239462Sdim bool isAllocationFunction(const FunctionDecl *FD, ASTContext &C) const; 235249423Sdim bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const; 236249423Sdim ///@} 237234353Sdim static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C, 238234353Sdim const CallExpr *CE, 239234353Sdim const OwnershipAttr* Att); 240234353Sdim static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, 241221345Sdim const Expr *SizeEx, SVal Init, 242249423Sdim ProgramStateRef State, 243249423Sdim AllocationFamily Family = AF_Malloc) { 244234353Sdim return MallocMemAux(C, CE, 245249423Sdim State->getSVal(SizeEx, C.getLocationContext()), 246249423Sdim Init, State, Family); 247218887Sdim } 248234353Sdim 249234353Sdim static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, 250221345Sdim SVal SizeEx, SVal Init, 251249423Sdim ProgramStateRef State, 252249423Sdim AllocationFamily Family = AF_Malloc); 253218887Sdim 254234353Sdim /// Update the RefState to reflect the new memory allocation. 255249423Sdim static ProgramStateRef 256249423Sdim MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State, 257249423Sdim AllocationFamily Family = AF_Malloc); 258218887Sdim 259234353Sdim ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE, 260234353Sdim const OwnershipAttr* Att) const; 261234353Sdim ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE, 262239462Sdim ProgramStateRef state, unsigned Num, 263243830Sdim bool Hold, 264243830Sdim bool &ReleasedAllocated, 265243830Sdim bool ReturnsNullOnFailure = false) const; 266239462Sdim ProgramStateRef FreeMemAux(CheckerContext &C, const Expr *Arg, 267239462Sdim const Expr *ParentExpr, 268243830Sdim ProgramStateRef State, 269243830Sdim bool Hold, 270243830Sdim bool &ReleasedAllocated, 271243830Sdim bool ReturnsNullOnFailure = false) const; 272234353Sdim 273234353Sdim ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE, 274234353Sdim bool FreesMemOnFailure) const; 275234353Sdim static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE); 276218887Sdim 277239462Sdim ///\brief Check if the memory associated with this symbol was released. 278239462Sdim bool isReleased(SymbolRef Sym, CheckerContext &C) const; 279239462Sdim 280249423Sdim bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const; 281234353Sdim 282263508Sdim /// Check if the function is known free memory, or if it is 283249423Sdim /// "interesting" and should be modeled explicitly. 284249423Sdim /// 285263508Sdim /// \param [out] EscapingSymbol A function might not free memory in general, 286263508Sdim /// but could be known to free a particular symbol. In this case, false is 287263508Sdim /// returned and the single escaping symbol is returned through the out 288263508Sdim /// parameter. 289263508Sdim /// 290249423Sdim /// We assume that pointers do not escape through calls to system functions 291249423Sdim /// not handled by this checker. 292263508Sdim bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call, 293263508Sdim ProgramStateRef State, 294263508Sdim SymbolRef &EscapingSymbol) const; 295234353Sdim 296249423Sdim // Implementation of the checkPointerEscape callabcks. 297249423Sdim ProgramStateRef checkPointerEscapeAux(ProgramStateRef State, 298249423Sdim const InvalidatedSymbols &Escaped, 299249423Sdim const CallEvent *Call, 300249423Sdim PointerEscapeKind Kind, 301249423Sdim bool(*CheckRefState)(const RefState*)) const; 302249423Sdim 303251662Sdim ///@{ 304251662Sdim /// Tells if a given family/call/symbol is tracked by the current checker. 305251662Sdim bool isTrackedByCurrentChecker(AllocationFamily Family) const; 306251662Sdim bool isTrackedByCurrentChecker(CheckerContext &C, 307251662Sdim const Stmt *AllocDeallocStmt) const; 308251662Sdim bool isTrackedByCurrentChecker(CheckerContext &C, SymbolRef Sym) const; 309251662Sdim ///@} 310226633Sdim static bool SummarizeValue(raw_ostream &os, SVal V); 311226633Sdim static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); 312249423Sdim void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range, 313249423Sdim const Expr *DeallocExpr) const; 314249423Sdim void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range, 315251662Sdim const Expr *DeallocExpr, const RefState *RS, 316263508Sdim SymbolRef Sym, bool OwnershipTransferred) const; 317249423Sdim void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range, 318249423Sdim const Expr *DeallocExpr, 319249423Sdim const Expr *AllocExpr = 0) const; 320249423Sdim void ReportUseAfterFree(CheckerContext &C, SourceRange Range, 321249423Sdim SymbolRef Sym) const; 322249423Sdim void ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released, 323249423Sdim SymbolRef Sym, SymbolRef PrevSym) const; 324234353Sdim 325234353Sdim /// Find the location of the allocation for Sym on the path leading to the 326234353Sdim /// exploded node N. 327234353Sdim LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym, 328234353Sdim CheckerContext &C) const; 329234353Sdim 330234353Sdim void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const; 331234353Sdim 332234353Sdim /// The bug visitor which allows us to print extra diagnostics along the 333234353Sdim /// BugReport path. For example, showing the allocation site of the leaked 334234353Sdim /// region. 335234353Sdim class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> { 336234353Sdim protected: 337234353Sdim enum NotificationMode { 338234353Sdim Normal, 339234353Sdim ReallocationFailed 340234353Sdim }; 341234353Sdim 342234353Sdim // The allocated region symbol tracked by the main analysis. 343234353Sdim SymbolRef Sym; 344234353Sdim 345239462Sdim // The mode we are in, i.e. what kind of diagnostics will be emitted. 346239462Sdim NotificationMode Mode; 347234353Sdim 348239462Sdim // A symbol from when the primary region should have been reallocated. 349239462Sdim SymbolRef FailedReallocSymbol; 350234353Sdim 351239462Sdim bool IsLeak; 352234353Sdim 353239462Sdim public: 354239462Sdim MallocBugVisitor(SymbolRef S, bool isLeak = false) 355239462Sdim : Sym(S), Mode(Normal), FailedReallocSymbol(0), IsLeak(isLeak) {} 356239462Sdim 357234353Sdim virtual ~MallocBugVisitor() {} 358234353Sdim 359234353Sdim void Profile(llvm::FoldingSetNodeID &ID) const { 360234353Sdim static int X = 0; 361234353Sdim ID.AddPointer(&X); 362234353Sdim ID.AddPointer(Sym); 363234353Sdim } 364234353Sdim 365234353Sdim inline bool isAllocated(const RefState *S, const RefState *SPrev, 366234353Sdim const Stmt *Stmt) { 367234353Sdim // Did not track -> allocated. Other state (released) -> allocated. 368249423Sdim return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) && 369234353Sdim (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated())); 370234353Sdim } 371234353Sdim 372234353Sdim inline bool isReleased(const RefState *S, const RefState *SPrev, 373234353Sdim const Stmt *Stmt) { 374234353Sdim // Did not track -> released. Other state (allocated) -> released. 375249423Sdim return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) && 376234353Sdim (S && S->isReleased()) && (!SPrev || !SPrev->isReleased())); 377234353Sdim } 378234353Sdim 379239462Sdim inline bool isRelinquished(const RefState *S, const RefState *SPrev, 380239462Sdim const Stmt *Stmt) { 381239462Sdim // Did not track -> relinquished. Other state (allocated) -> relinquished. 382239462Sdim return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) || 383239462Sdim isa<ObjCPropertyRefExpr>(Stmt)) && 384239462Sdim (S && S->isRelinquished()) && 385239462Sdim (!SPrev || !SPrev->isRelinquished())); 386239462Sdim } 387239462Sdim 388234353Sdim inline bool isReallocFailedCheck(const RefState *S, const RefState *SPrev, 389234353Sdim const Stmt *Stmt) { 390234353Sdim // If the expression is not a call, and the state change is 391234353Sdim // released -> allocated, it must be the realloc return value 392234353Sdim // check. If we have to handle more cases here, it might be cleaner just 393234353Sdim // to track this extra bit in the state itself. 394234353Sdim return ((!Stmt || !isa<CallExpr>(Stmt)) && 395234353Sdim (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated())); 396234353Sdim } 397234353Sdim 398234353Sdim PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 399234353Sdim const ExplodedNode *PrevN, 400234353Sdim BugReporterContext &BRC, 401234353Sdim BugReport &BR); 402239462Sdim 403239462Sdim PathDiagnosticPiece* getEndPath(BugReporterContext &BRC, 404239462Sdim const ExplodedNode *EndPathNode, 405239462Sdim BugReport &BR) { 406239462Sdim if (!IsLeak) 407239462Sdim return 0; 408239462Sdim 409239462Sdim PathDiagnosticLocation L = 410239462Sdim PathDiagnosticLocation::createEndOfPath(EndPathNode, 411239462Sdim BRC.getSourceManager()); 412239462Sdim // Do not add the statement itself as a range in case of leak. 413239462Sdim return new PathDiagnosticEventPiece(L, BR.getDescription(), false); 414239462Sdim } 415239462Sdim 416234353Sdim private: 417234353Sdim class StackHintGeneratorForReallocationFailed 418234353Sdim : public StackHintGeneratorForSymbol { 419234353Sdim public: 420234353Sdim StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M) 421234353Sdim : StackHintGeneratorForSymbol(S, M) {} 422234353Sdim 423234353Sdim virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) { 424243830Sdim // Printed parameters start at 1, not 0. 425243830Sdim ++ArgIndex; 426243830Sdim 427234353Sdim SmallString<200> buf; 428234353Sdim llvm::raw_svector_ostream os(buf); 429234353Sdim 430243830Sdim os << "Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex) 431243830Sdim << " parameter failed"; 432234353Sdim 433234353Sdim return os.str(); 434234353Sdim } 435234353Sdim 436234353Sdim virtual std::string getMessageForReturn(const CallExpr *CallExpr) { 437234353Sdim return "Reallocation of returned value failed"; 438234353Sdim } 439234353Sdim }; 440234353Sdim }; 441218887Sdim}; 442218887Sdim} // end anonymous namespace 443218887Sdim 444243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState) 445243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair) 446234353Sdim 447243830Sdim// A map from the freed symbol to the symbol representing the return value of 448243830Sdim// the free function. 449243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef) 450218887Sdim 451234353Sdimnamespace { 452234353Sdimclass StopTrackingCallback : public SymbolVisitor { 453234353Sdim ProgramStateRef state; 454234353Sdimpublic: 455234353Sdim StopTrackingCallback(ProgramStateRef st) : state(st) {} 456234353Sdim ProgramStateRef getState() const { return state; } 457218887Sdim 458234353Sdim bool VisitSymbol(SymbolRef sym) { 459234353Sdim state = state->remove<RegionState>(sym); 460234353Sdim return true; 461234353Sdim } 462234353Sdim}; 463234353Sdim} // end anonymous namespace 464218887Sdim 465234353Sdimvoid MallocChecker::initIdentifierInfo(ASTContext &Ctx) const { 466239462Sdim if (II_malloc) 467239462Sdim return; 468239462Sdim II_malloc = &Ctx.Idents.get("malloc"); 469239462Sdim II_free = &Ctx.Idents.get("free"); 470239462Sdim II_realloc = &Ctx.Idents.get("realloc"); 471239462Sdim II_reallocf = &Ctx.Idents.get("reallocf"); 472239462Sdim II_calloc = &Ctx.Idents.get("calloc"); 473239462Sdim II_valloc = &Ctx.Idents.get("valloc"); 474239462Sdim II_strdup = &Ctx.Idents.get("strdup"); 475239462Sdim II_strndup = &Ctx.Idents.get("strndup"); 476234353Sdim} 477218887Sdim 478234353Sdimbool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const { 479239462Sdim if (isFreeFunction(FD, C)) 480239462Sdim return true; 481239462Sdim 482239462Sdim if (isAllocationFunction(FD, C)) 483239462Sdim return true; 484239462Sdim 485249423Sdim if (isStandardNewDelete(FD, C)) 486249423Sdim return true; 487249423Sdim 488239462Sdim return false; 489239462Sdim} 490239462Sdim 491239462Sdimbool MallocChecker::isAllocationFunction(const FunctionDecl *FD, 492239462Sdim ASTContext &C) const { 493234353Sdim if (!FD) 494234353Sdim return false; 495218887Sdim 496239462Sdim if (FD->getKind() == Decl::Function) { 497239462Sdim IdentifierInfo *FunI = FD->getIdentifier(); 498239462Sdim initIdentifierInfo(C); 499218887Sdim 500239462Sdim if (FunI == II_malloc || FunI == II_realloc || 501239462Sdim FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc || 502239462Sdim FunI == II_strdup || FunI == II_strndup) 503239462Sdim return true; 504239462Sdim } 505218887Sdim 506239462Sdim if (Filter.CMallocOptimistic && FD->hasAttrs()) 507239462Sdim for (specific_attr_iterator<OwnershipAttr> 508239462Sdim i = FD->specific_attr_begin<OwnershipAttr>(), 509239462Sdim e = FD->specific_attr_end<OwnershipAttr>(); 510239462Sdim i != e; ++i) 511239462Sdim if ((*i)->getOwnKind() == OwnershipAttr::Returns) 512239462Sdim return true; 513239462Sdim return false; 514239462Sdim} 515218887Sdim 516239462Sdimbool MallocChecker::isFreeFunction(const FunctionDecl *FD, ASTContext &C) const { 517239462Sdim if (!FD) 518239462Sdim return false; 519234353Sdim 520239462Sdim if (FD->getKind() == Decl::Function) { 521239462Sdim IdentifierInfo *FunI = FD->getIdentifier(); 522239462Sdim initIdentifierInfo(C); 523239462Sdim 524239462Sdim if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf) 525239462Sdim return true; 526239462Sdim } 527239462Sdim 528239462Sdim if (Filter.CMallocOptimistic && FD->hasAttrs()) 529239462Sdim for (specific_attr_iterator<OwnershipAttr> 530239462Sdim i = FD->specific_attr_begin<OwnershipAttr>(), 531239462Sdim e = FD->specific_attr_end<OwnershipAttr>(); 532239462Sdim i != e; ++i) 533239462Sdim if ((*i)->getOwnKind() == OwnershipAttr::Takes || 534239462Sdim (*i)->getOwnKind() == OwnershipAttr::Holds) 535239462Sdim return true; 536234353Sdim return false; 537234353Sdim} 538234353Sdim 539249423Sdim// Tells if the callee is one of the following: 540249423Sdim// 1) A global non-placement new/delete operator function. 541249423Sdim// 2) A global placement operator function with the single placement argument 542249423Sdim// of type std::nothrow_t. 543249423Sdimbool MallocChecker::isStandardNewDelete(const FunctionDecl *FD, 544249423Sdim ASTContext &C) const { 545249423Sdim if (!FD) 546249423Sdim return false; 547249423Sdim 548249423Sdim OverloadedOperatorKind Kind = FD->getOverloadedOperator(); 549249423Sdim if (Kind != OO_New && Kind != OO_Array_New && 550249423Sdim Kind != OO_Delete && Kind != OO_Array_Delete) 551249423Sdim return false; 552249423Sdim 553249423Sdim // Skip all operator new/delete methods. 554249423Sdim if (isa<CXXMethodDecl>(FD)) 555249423Sdim return false; 556249423Sdim 557249423Sdim // Return true if tested operator is a standard placement nothrow operator. 558249423Sdim if (FD->getNumParams() == 2) { 559249423Sdim QualType T = FD->getParamDecl(1)->getType(); 560249423Sdim if (const IdentifierInfo *II = T.getBaseTypeIdentifier()) 561249423Sdim return II->getName().equals("nothrow_t"); 562249423Sdim } 563249423Sdim 564249423Sdim // Skip placement operators. 565249423Sdim if (FD->getNumParams() != 1 || FD->isVariadic()) 566249423Sdim return false; 567249423Sdim 568249423Sdim // One of the standard new/new[]/delete/delete[] non-placement operators. 569249423Sdim return true; 570249423Sdim} 571249423Sdim 572234353Sdimvoid MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { 573243830Sdim if (C.wasInlined) 574243830Sdim return; 575243830Sdim 576234353Sdim const FunctionDecl *FD = C.getCalleeDecl(CE); 577234353Sdim if (!FD) 578234353Sdim return; 579234353Sdim 580239462Sdim ProgramStateRef State = C.getState(); 581243830Sdim bool ReleasedAllocatedMemory = false; 582234353Sdim 583239462Sdim if (FD->getKind() == Decl::Function) { 584239462Sdim initIdentifierInfo(C.getASTContext()); 585239462Sdim IdentifierInfo *FunI = FD->getIdentifier(); 586239462Sdim 587239462Sdim if (FunI == II_malloc || FunI == II_valloc) { 588239462Sdim if (CE->getNumArgs() < 1) 589239462Sdim return; 590239462Sdim State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State); 591239462Sdim } else if (FunI == II_realloc) { 592239462Sdim State = ReallocMem(C, CE, false); 593239462Sdim } else if (FunI == II_reallocf) { 594239462Sdim State = ReallocMem(C, CE, true); 595239462Sdim } else if (FunI == II_calloc) { 596239462Sdim State = CallocMem(C, CE); 597239462Sdim } else if (FunI == II_free) { 598243830Sdim State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory); 599239462Sdim } else if (FunI == II_strdup) { 600239462Sdim State = MallocUpdateRefState(C, CE, State); 601239462Sdim } else if (FunI == II_strndup) { 602239462Sdim State = MallocUpdateRefState(C, CE, State); 603239462Sdim } 604249423Sdim else if (isStandardNewDelete(FD, C.getASTContext())) { 605249423Sdim // Process direct calls to operator new/new[]/delete/delete[] functions 606249423Sdim // as distinct from new/new[]/delete/delete[] expressions that are 607249423Sdim // processed by the checkPostStmt callbacks for CXXNewExpr and 608249423Sdim // CXXDeleteExpr. 609249423Sdim OverloadedOperatorKind K = FD->getOverloadedOperator(); 610249423Sdim if (K == OO_New) 611249423Sdim State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, 612249423Sdim AF_CXXNew); 613249423Sdim else if (K == OO_Array_New) 614249423Sdim State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State, 615249423Sdim AF_CXXNewArray); 616249423Sdim else if (K == OO_Delete || K == OO_Array_Delete) 617249423Sdim State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory); 618249423Sdim else 619249423Sdim llvm_unreachable("not a new/delete operator"); 620249423Sdim } 621239462Sdim } 622239462Sdim 623249423Sdim if (Filter.CMallocOptimistic || Filter.CMismatchedDeallocatorChecker) { 624234353Sdim // Check all the attributes, if there are any. 625234353Sdim // There can be multiple of these attributes. 626234353Sdim if (FD->hasAttrs()) 627234353Sdim for (specific_attr_iterator<OwnershipAttr> 628234353Sdim i = FD->specific_attr_begin<OwnershipAttr>(), 629234353Sdim e = FD->specific_attr_end<OwnershipAttr>(); 630234353Sdim i != e; ++i) { 631234353Sdim switch ((*i)->getOwnKind()) { 632234353Sdim case OwnershipAttr::Returns: 633234353Sdim State = MallocMemReturnsAttr(C, CE, *i); 634234353Sdim break; 635234353Sdim case OwnershipAttr::Takes: 636234353Sdim case OwnershipAttr::Holds: 637234353Sdim State = FreeMemAttr(C, CE, *i); 638234353Sdim break; 639234353Sdim } 640218887Sdim } 641218887Sdim } 642234353Sdim C.addTransition(State); 643218887Sdim} 644218887Sdim 645249423Sdimvoid MallocChecker::checkPostStmt(const CXXNewExpr *NE, 646249423Sdim CheckerContext &C) const { 647249423Sdim 648249423Sdim if (NE->getNumPlacementArgs()) 649249423Sdim for (CXXNewExpr::const_arg_iterator I = NE->placement_arg_begin(), 650249423Sdim E = NE->placement_arg_end(); I != E; ++I) 651249423Sdim if (SymbolRef Sym = C.getSVal(*I).getAsSymbol()) 652249423Sdim checkUseAfterFree(Sym, C, *I); 653249423Sdim 654249423Sdim if (!isStandardNewDelete(NE->getOperatorNew(), C.getASTContext())) 655249423Sdim return; 656249423Sdim 657249423Sdim ProgramStateRef State = C.getState(); 658249423Sdim // The return value from operator new is bound to a specified initialization 659249423Sdim // value (if any) and we don't want to loose this value. So we call 660249423Sdim // MallocUpdateRefState() instead of MallocMemAux() which breakes the 661249423Sdim // existing binding. 662249423Sdim State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray 663249423Sdim : AF_CXXNew); 664249423Sdim C.addTransition(State); 665249423Sdim} 666249423Sdim 667249423Sdimvoid MallocChecker::checkPreStmt(const CXXDeleteExpr *DE, 668249423Sdim CheckerContext &C) const { 669249423Sdim 670249423Sdim if (!Filter.CNewDeleteChecker) 671249423Sdim if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol()) 672249423Sdim checkUseAfterFree(Sym, C, DE->getArgument()); 673249423Sdim 674249423Sdim if (!isStandardNewDelete(DE->getOperatorDelete(), C.getASTContext())) 675249423Sdim return; 676249423Sdim 677249423Sdim ProgramStateRef State = C.getState(); 678249423Sdim bool ReleasedAllocated; 679249423Sdim State = FreeMemAux(C, DE->getArgument(), DE, State, 680249423Sdim /*Hold*/false, ReleasedAllocated); 681249423Sdim 682249423Sdim C.addTransition(State); 683249423Sdim} 684249423Sdim 685249423Sdimstatic bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call) { 686249423Sdim // If the first selector piece is one of the names below, assume that the 687249423Sdim // object takes ownership of the memory, promising to eventually deallocate it 688249423Sdim // with free(). 689249423Sdim // Ex: [NSData dataWithBytesNoCopy:bytes length:10]; 690249423Sdim // (...unless a 'freeWhenDone' parameter is false, but that's checked later.) 691249423Sdim StringRef FirstSlot = Call.getSelector().getNameForSlot(0); 692249423Sdim if (FirstSlot == "dataWithBytesNoCopy" || 693249423Sdim FirstSlot == "initWithBytesNoCopy" || 694249423Sdim FirstSlot == "initWithCharactersNoCopy") 695249423Sdim return true; 696249423Sdim 697249423Sdim return false; 698249423Sdim} 699249423Sdim 700249423Sdimstatic Optional<bool> getFreeWhenDoneArg(const ObjCMethodCall &Call) { 701239462Sdim Selector S = Call.getSelector(); 702249423Sdim 703249423Sdim // FIXME: We should not rely on fully-constrained symbols being folded. 704239462Sdim for (unsigned i = 1; i < S.getNumArgs(); ++i) 705239462Sdim if (S.getNameForSlot(i).equals("freeWhenDone")) 706249423Sdim return !Call.getArgSVal(i).isZeroConstant(); 707239462Sdim 708249423Sdim return None; 709239462Sdim} 710239462Sdim 711243830Sdimvoid MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call, 712243830Sdim CheckerContext &C) const { 713249423Sdim if (C.wasInlined) 714249423Sdim return; 715243830Sdim 716249423Sdim if (!isKnownDeallocObjCMethodName(Call)) 717249423Sdim return; 718249423Sdim 719249423Sdim if (Optional<bool> FreeWhenDone = getFreeWhenDoneArg(Call)) 720249423Sdim if (!*FreeWhenDone) 721249423Sdim return; 722249423Sdim 723249423Sdim bool ReleasedAllocatedMemory; 724249423Sdim ProgramStateRef State = FreeMemAux(C, Call.getArgExpr(0), 725249423Sdim Call.getOriginExpr(), C.getState(), 726249423Sdim /*Hold=*/true, ReleasedAllocatedMemory, 727249423Sdim /*RetNullOnFailure=*/true); 728249423Sdim 729249423Sdim C.addTransition(State); 730239462Sdim} 731239462Sdim 732234353SdimProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C, 733234353Sdim const CallExpr *CE, 734234353Sdim const OwnershipAttr* Att) { 735218887Sdim if (Att->getModule() != "malloc") 736234353Sdim return 0; 737218887Sdim 738218887Sdim OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 739218887Sdim if (I != E) { 740234353Sdim return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); 741218887Sdim } 742234353Sdim return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState()); 743218887Sdim} 744218887Sdim 745234353SdimProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, 746218887Sdim const CallExpr *CE, 747218887Sdim SVal Size, SVal Init, 748249423Sdim ProgramStateRef State, 749249423Sdim AllocationFamily Family) { 750218887Sdim 751239462Sdim // Bind the return value to the symbolic value from the heap region. 752239462Sdim // TODO: We could rewrite post visit to eval call; 'malloc' does not have 753239462Sdim // side effects other than what we model here. 754243830Sdim unsigned Count = C.blockCount(); 755239462Sdim SValBuilder &svalBuilder = C.getSValBuilder(); 756239462Sdim const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); 757249423Sdim DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count) 758249423Sdim .castAs<DefinedSVal>(); 759249423Sdim State = State->BindExpr(CE, C.getLocationContext(), RetVal); 760239462Sdim 761234353Sdim // We expect the malloc functions to return a pointer. 762249423Sdim if (!RetVal.getAs<Loc>()) 763234353Sdim return 0; 764218887Sdim 765218887Sdim // Fill the region with the initialization value. 766249423Sdim State = State->bindDefault(RetVal, Init); 767218887Sdim 768218887Sdim // Set the region's extent equal to the Size parameter. 769234353Sdim const SymbolicRegion *R = 770239462Sdim dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion()); 771234353Sdim if (!R) 772234353Sdim return 0; 773249423Sdim if (Optional<DefinedOrUnknownSVal> DefinedSize = 774249423Sdim Size.getAs<DefinedOrUnknownSVal>()) { 775234353Sdim SValBuilder &svalBuilder = C.getSValBuilder(); 776234353Sdim DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 777234353Sdim DefinedOrUnknownSVal extentMatchesSize = 778249423Sdim svalBuilder.evalEQ(State, Extent, *DefinedSize); 779218887Sdim 780249423Sdim State = State->assume(extentMatchesSize, true); 781249423Sdim assert(State); 782234353Sdim } 783218887Sdim 784249423Sdim return MallocUpdateRefState(C, CE, State, Family); 785234353Sdim} 786234353Sdim 787234353SdimProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C, 788249423Sdim const Expr *E, 789249423Sdim ProgramStateRef State, 790249423Sdim AllocationFamily Family) { 791234353Sdim // Get the return value. 792249423Sdim SVal retVal = State->getSVal(E, C.getLocationContext()); 793234353Sdim 794234353Sdim // We expect the malloc functions to return a pointer. 795249423Sdim if (!retVal.getAs<Loc>()) 796234353Sdim return 0; 797234353Sdim 798218887Sdim SymbolRef Sym = retVal.getAsLocSymbol(); 799218887Sdim assert(Sym); 800218887Sdim 801218887Sdim // Set the symbol's state to Allocated. 802249423Sdim return State->set<RegionState>(Sym, RefState::getAllocated(Family, E)); 803218887Sdim} 804218887Sdim 805234353SdimProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, 806234353Sdim const CallExpr *CE, 807234353Sdim const OwnershipAttr* Att) const { 808218887Sdim if (Att->getModule() != "malloc") 809234353Sdim return 0; 810218887Sdim 811234353Sdim ProgramStateRef State = C.getState(); 812243830Sdim bool ReleasedAllocated = false; 813234353Sdim 814218887Sdim for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 815218887Sdim I != E; ++I) { 816234353Sdim ProgramStateRef StateI = FreeMemAux(C, CE, State, *I, 817243830Sdim Att->getOwnKind() == OwnershipAttr::Holds, 818243830Sdim ReleasedAllocated); 819234353Sdim if (StateI) 820234353Sdim State = StateI; 821218887Sdim } 822234353Sdim return State; 823218887Sdim} 824218887Sdim 825234353SdimProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, 826234353Sdim const CallExpr *CE, 827234353Sdim ProgramStateRef state, 828234353Sdim unsigned Num, 829243830Sdim bool Hold, 830243830Sdim bool &ReleasedAllocated, 831243830Sdim bool ReturnsNullOnFailure) const { 832234353Sdim if (CE->getNumArgs() < (Num + 1)) 833234353Sdim return 0; 834234353Sdim 835243830Sdim return FreeMemAux(C, CE->getArg(Num), CE, state, Hold, 836243830Sdim ReleasedAllocated, ReturnsNullOnFailure); 837239462Sdim} 838239462Sdim 839243830Sdim/// Checks if the previous call to free on the given symbol failed - if free 840243830Sdim/// failed, returns true. Also, returns the corresponding return value symbol. 841249423Sdimstatic bool didPreviousFreeFail(ProgramStateRef State, 842249423Sdim SymbolRef Sym, SymbolRef &RetStatusSymbol) { 843243830Sdim const SymbolRef *Ret = State->get<FreeReturnValue>(Sym); 844243830Sdim if (Ret) { 845243830Sdim assert(*Ret && "We should not store the null return symbol"); 846243830Sdim ConstraintManager &CMgr = State->getConstraintManager(); 847243830Sdim ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret); 848243830Sdim RetStatusSymbol = *Ret; 849243830Sdim return FreeFailed.isConstrainedTrue(); 850243830Sdim } 851243830Sdim return false; 852243830Sdim} 853243830Sdim 854249423SdimAllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C, 855249423Sdim const Stmt *S) const { 856249423Sdim if (!S) 857249423Sdim return AF_None; 858249423Sdim 859249423Sdim if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { 860249423Sdim const FunctionDecl *FD = C.getCalleeDecl(CE); 861249423Sdim 862249423Sdim if (!FD) 863249423Sdim FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); 864249423Sdim 865249423Sdim ASTContext &Ctx = C.getASTContext(); 866249423Sdim 867249423Sdim if (isAllocationFunction(FD, Ctx) || isFreeFunction(FD, Ctx)) 868249423Sdim return AF_Malloc; 869249423Sdim 870249423Sdim if (isStandardNewDelete(FD, Ctx)) { 871249423Sdim OverloadedOperatorKind Kind = FD->getOverloadedOperator(); 872249423Sdim if (Kind == OO_New || Kind == OO_Delete) 873249423Sdim return AF_CXXNew; 874249423Sdim else if (Kind == OO_Array_New || Kind == OO_Array_Delete) 875249423Sdim return AF_CXXNewArray; 876249423Sdim } 877249423Sdim 878249423Sdim return AF_None; 879249423Sdim } 880249423Sdim 881249423Sdim if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S)) 882249423Sdim return NE->isArray() ? AF_CXXNewArray : AF_CXXNew; 883249423Sdim 884249423Sdim if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(S)) 885249423Sdim return DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew; 886249423Sdim 887249423Sdim if (isa<ObjCMessageExpr>(S)) 888249423Sdim return AF_Malloc; 889249423Sdim 890249423Sdim return AF_None; 891249423Sdim} 892249423Sdim 893249423Sdimbool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C, 894249423Sdim const Expr *E) const { 895249423Sdim if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { 896249423Sdim // FIXME: This doesn't handle indirect calls. 897249423Sdim const FunctionDecl *FD = CE->getDirectCallee(); 898249423Sdim if (!FD) 899249423Sdim return false; 900249423Sdim 901249423Sdim os << *FD; 902249423Sdim if (!FD->isOverloadedOperator()) 903249423Sdim os << "()"; 904249423Sdim return true; 905249423Sdim } 906249423Sdim 907249423Sdim if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) { 908249423Sdim if (Msg->isInstanceMessage()) 909249423Sdim os << "-"; 910249423Sdim else 911249423Sdim os << "+"; 912249423Sdim os << Msg->getSelector().getAsString(); 913249423Sdim return true; 914249423Sdim } 915249423Sdim 916249423Sdim if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) { 917249423Sdim os << "'" 918249423Sdim << getOperatorSpelling(NE->getOperatorNew()->getOverloadedOperator()) 919249423Sdim << "'"; 920249423Sdim return true; 921249423Sdim } 922249423Sdim 923249423Sdim if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E)) { 924249423Sdim os << "'" 925249423Sdim << getOperatorSpelling(DE->getOperatorDelete()->getOverloadedOperator()) 926249423Sdim << "'"; 927249423Sdim return true; 928249423Sdim } 929249423Sdim 930249423Sdim return false; 931249423Sdim} 932249423Sdim 933249423Sdimvoid MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C, 934249423Sdim const Expr *E) const { 935249423Sdim AllocationFamily Family = getAllocationFamily(C, E); 936249423Sdim 937249423Sdim switch(Family) { 938249423Sdim case AF_Malloc: os << "malloc()"; return; 939249423Sdim case AF_CXXNew: os << "'new'"; return; 940249423Sdim case AF_CXXNewArray: os << "'new[]'"; return; 941249423Sdim case AF_None: llvm_unreachable("not a deallocation expression"); 942249423Sdim } 943249423Sdim} 944249423Sdim 945249423Sdimvoid MallocChecker::printExpectedDeallocName(raw_ostream &os, 946249423Sdim AllocationFamily Family) const { 947249423Sdim switch(Family) { 948249423Sdim case AF_Malloc: os << "free()"; return; 949249423Sdim case AF_CXXNew: os << "'delete'"; return; 950249423Sdim case AF_CXXNewArray: os << "'delete[]'"; return; 951249423Sdim case AF_None: llvm_unreachable("suspicious AF_None argument"); 952249423Sdim } 953249423Sdim} 954249423Sdim 955239462SdimProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, 956239462Sdim const Expr *ArgExpr, 957239462Sdim const Expr *ParentExpr, 958243830Sdim ProgramStateRef State, 959243830Sdim bool Hold, 960243830Sdim bool &ReleasedAllocated, 961243830Sdim bool ReturnsNullOnFailure) const { 962239462Sdim 963243830Sdim SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext()); 964249423Sdim if (!ArgVal.getAs<DefinedOrUnknownSVal>()) 965234353Sdim return 0; 966249423Sdim DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>(); 967218887Sdim 968218887Sdim // Check for null dereferences. 969249423Sdim if (!location.getAs<Loc>()) 970234353Sdim return 0; 971218887Sdim 972234353Sdim // The explicit NULL case, no operation is performed. 973234353Sdim ProgramStateRef notNullState, nullState; 974243830Sdim llvm::tie(notNullState, nullState) = State->assume(location); 975218887Sdim if (nullState && !notNullState) 976234353Sdim return 0; 977218887Sdim 978218887Sdim // Unknown values could easily be okay 979218887Sdim // Undefined values are handled elsewhere 980218887Sdim if (ArgVal.isUnknownOrUndef()) 981234353Sdim return 0; 982218887Sdim 983218887Sdim const MemRegion *R = ArgVal.getAsRegion(); 984218887Sdim 985218887Sdim // Nonlocs can't be freed, of course. 986218887Sdim // Non-region locations (labels and fixed addresses) also shouldn't be freed. 987218887Sdim if (!R) { 988249423Sdim ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); 989234353Sdim return 0; 990218887Sdim } 991218887Sdim 992218887Sdim R = R->StripCasts(); 993218887Sdim 994218887Sdim // Blocks might show up as heap data, but should not be free()d 995218887Sdim if (isa<BlockDataRegion>(R)) { 996249423Sdim ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); 997234353Sdim return 0; 998218887Sdim } 999218887Sdim 1000218887Sdim const MemSpaceRegion *MS = R->getMemorySpace(); 1001218887Sdim 1002249423Sdim // Parameters, locals, statics, globals, and memory returned by alloca() 1003249423Sdim // shouldn't be freed. 1004218887Sdim if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) { 1005218887Sdim // FIXME: at the time this code was written, malloc() regions were 1006218887Sdim // represented by conjured symbols, which are all in UnknownSpaceRegion. 1007218887Sdim // This means that there isn't actually anything from HeapSpaceRegion 1008218887Sdim // that should be freed, even though we allow it here. 1009218887Sdim // Of course, free() can work on memory allocated outside the current 1010218887Sdim // function, so UnknownSpaceRegion is always a possibility. 1011218887Sdim // False negatives are better than false positives. 1012218887Sdim 1013249423Sdim ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr); 1014234353Sdim return 0; 1015218887Sdim } 1016249423Sdim 1017249423Sdim const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion()); 1018218887Sdim // Various cases could lead to non-symbol values here. 1019218887Sdim // For now, ignore them. 1020249423Sdim if (!SrBase) 1021234353Sdim return 0; 1022218887Sdim 1023249423Sdim SymbolRef SymBase = SrBase->getSymbol(); 1024249423Sdim const RefState *RsBase = State->get<RegionState>(SymBase); 1025243830Sdim SymbolRef PreviousRetStatusSymbol = 0; 1026218887Sdim 1027249423Sdim if (RsBase) { 1028243830Sdim 1029251662Sdim // Check for double free first. 1030251662Sdim if ((RsBase->isReleased() || RsBase->isRelinquished()) && 1031249423Sdim !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) { 1032249423Sdim ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(), 1033249423Sdim SymBase, PreviousRetStatusSymbol); 1034249423Sdim return 0; 1035249423Sdim 1036251662Sdim // If the pointer is allocated or escaped, but we are now trying to free it, 1037251662Sdim // check that the call to free is proper. 1038251662Sdim } else if (RsBase->isAllocated() || RsBase->isEscaped()) { 1039251662Sdim 1040251662Sdim // Check if an expected deallocation function matches the real one. 1041251662Sdim bool DeallocMatchesAlloc = 1042251662Sdim RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr); 1043251662Sdim if (!DeallocMatchesAlloc) { 1044251662Sdim ReportMismatchedDealloc(C, ArgExpr->getSourceRange(), 1045263508Sdim ParentExpr, RsBase, SymBase, Hold); 1046251662Sdim return 0; 1047251662Sdim } 1048251662Sdim 1049251662Sdim // Check if the memory location being freed is the actual location 1050251662Sdim // allocated, or an offset. 1051251662Sdim RegionOffset Offset = R->getAsOffset(); 1052251662Sdim if (Offset.isValid() && 1053251662Sdim !Offset.hasSymbolicOffset() && 1054251662Sdim Offset.getOffset() != 0) { 1055251662Sdim const Expr *AllocExpr = cast<Expr>(RsBase->getStmt()); 1056251662Sdim ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, 1057251662Sdim AllocExpr); 1058251662Sdim return 0; 1059251662Sdim } 1060249423Sdim } 1061218887Sdim } 1062218887Sdim 1063263508Sdim ReleasedAllocated = (RsBase != 0) && RsBase->isAllocated(); 1064243830Sdim 1065243830Sdim // Clean out the info on previous call to free return info. 1066249423Sdim State = State->remove<FreeReturnValue>(SymBase); 1067243830Sdim 1068243830Sdim // Keep track of the return value. If it is NULL, we will know that free 1069243830Sdim // failed. 1070243830Sdim if (ReturnsNullOnFailure) { 1071243830Sdim SVal RetVal = C.getSVal(ParentExpr); 1072243830Sdim SymbolRef RetStatusSymbol = RetVal.getAsSymbol(); 1073243830Sdim if (RetStatusSymbol) { 1074249423Sdim C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol); 1075249423Sdim State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol); 1076243830Sdim } 1077243830Sdim } 1078243830Sdim 1079251662Sdim AllocationFamily Family = RsBase ? RsBase->getAllocationFamily() 1080251662Sdim : getAllocationFamily(C, ParentExpr); 1081218887Sdim // Normal free. 1082218887Sdim if (Hold) 1083249423Sdim return State->set<RegionState>(SymBase, 1084249423Sdim RefState::getRelinquished(Family, 1085249423Sdim ParentExpr)); 1086249423Sdim 1087249423Sdim return State->set<RegionState>(SymBase, 1088249423Sdim RefState::getReleased(Family, ParentExpr)); 1089218887Sdim} 1090218887Sdim 1091251662Sdimbool MallocChecker::isTrackedByCurrentChecker(AllocationFamily Family) const { 1092249423Sdim switch (Family) { 1093249423Sdim case AF_Malloc: { 1094249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic) 1095249423Sdim return false; 1096249423Sdim return true; 1097249423Sdim } 1098249423Sdim case AF_CXXNew: 1099249423Sdim case AF_CXXNewArray: { 1100249423Sdim if (!Filter.CNewDeleteChecker) 1101249423Sdim return false; 1102249423Sdim return true; 1103249423Sdim } 1104249423Sdim case AF_None: { 1105251662Sdim llvm_unreachable("no family"); 1106249423Sdim } 1107249423Sdim } 1108249423Sdim llvm_unreachable("unhandled family"); 1109249423Sdim} 1110249423Sdim 1111251662Sdimbool 1112251662SdimMallocChecker::isTrackedByCurrentChecker(CheckerContext &C, 1113251662Sdim const Stmt *AllocDeallocStmt) const { 1114251662Sdim return isTrackedByCurrentChecker(getAllocationFamily(C, AllocDeallocStmt)); 1115249423Sdim} 1116249423Sdim 1117251662Sdimbool MallocChecker::isTrackedByCurrentChecker(CheckerContext &C, 1118251662Sdim SymbolRef Sym) const { 1119251662Sdim 1120249423Sdim const RefState *RS = C.getState()->get<RegionState>(Sym); 1121251662Sdim assert(RS); 1122251662Sdim return isTrackedByCurrentChecker(RS->getAllocationFamily()); 1123249423Sdim} 1124249423Sdim 1125226633Sdimbool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { 1126249423Sdim if (Optional<nonloc::ConcreteInt> IntVal = V.getAs<nonloc::ConcreteInt>()) 1127218887Sdim os << "an integer (" << IntVal->getValue() << ")"; 1128249423Sdim else if (Optional<loc::ConcreteInt> ConstAddr = V.getAs<loc::ConcreteInt>()) 1129218887Sdim os << "a constant address (" << ConstAddr->getValue() << ")"; 1130249423Sdim else if (Optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>()) 1131218887Sdim os << "the address of the label '" << Label->getLabel()->getName() << "'"; 1132218887Sdim else 1133218887Sdim return false; 1134218887Sdim 1135218887Sdim return true; 1136218887Sdim} 1137218887Sdim 1138226633Sdimbool MallocChecker::SummarizeRegion(raw_ostream &os, 1139218887Sdim const MemRegion *MR) { 1140218887Sdim switch (MR->getKind()) { 1141218887Sdim case MemRegion::FunctionTextRegionKind: { 1142243830Sdim const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 1143218887Sdim if (FD) 1144226633Sdim os << "the address of the function '" << *FD << '\''; 1145218887Sdim else 1146218887Sdim os << "the address of a function"; 1147218887Sdim return true; 1148218887Sdim } 1149218887Sdim case MemRegion::BlockTextRegionKind: 1150218887Sdim os << "block text"; 1151218887Sdim return true; 1152218887Sdim case MemRegion::BlockDataRegionKind: 1153218887Sdim // FIXME: where the block came from? 1154218887Sdim os << "a block"; 1155218887Sdim return true; 1156218887Sdim default: { 1157218887Sdim const MemSpaceRegion *MS = MR->getMemorySpace(); 1158218887Sdim 1159234353Sdim if (isa<StackLocalsSpaceRegion>(MS)) { 1160218887Sdim const VarRegion *VR = dyn_cast<VarRegion>(MR); 1161218887Sdim const VarDecl *VD; 1162218887Sdim if (VR) 1163218887Sdim VD = VR->getDecl(); 1164218887Sdim else 1165218887Sdim VD = NULL; 1166218887Sdim 1167218887Sdim if (VD) 1168218887Sdim os << "the address of the local variable '" << VD->getName() << "'"; 1169218887Sdim else 1170218887Sdim os << "the address of a local stack variable"; 1171218887Sdim return true; 1172218887Sdim } 1173234353Sdim 1174234353Sdim if (isa<StackArgumentsSpaceRegion>(MS)) { 1175218887Sdim const VarRegion *VR = dyn_cast<VarRegion>(MR); 1176218887Sdim const VarDecl *VD; 1177218887Sdim if (VR) 1178218887Sdim VD = VR->getDecl(); 1179218887Sdim else 1180218887Sdim VD = NULL; 1181218887Sdim 1182218887Sdim if (VD) 1183218887Sdim os << "the address of the parameter '" << VD->getName() << "'"; 1184218887Sdim else 1185218887Sdim os << "the address of a parameter"; 1186218887Sdim return true; 1187218887Sdim } 1188234353Sdim 1189234353Sdim if (isa<GlobalsSpaceRegion>(MS)) { 1190218887Sdim const VarRegion *VR = dyn_cast<VarRegion>(MR); 1191218887Sdim const VarDecl *VD; 1192218887Sdim if (VR) 1193218887Sdim VD = VR->getDecl(); 1194218887Sdim else 1195218887Sdim VD = NULL; 1196218887Sdim 1197218887Sdim if (VD) { 1198218887Sdim if (VD->isStaticLocal()) 1199218887Sdim os << "the address of the static variable '" << VD->getName() << "'"; 1200218887Sdim else 1201218887Sdim os << "the address of the global variable '" << VD->getName() << "'"; 1202218887Sdim } else 1203218887Sdim os << "the address of a global variable"; 1204218887Sdim return true; 1205218887Sdim } 1206234353Sdim 1207234353Sdim return false; 1208218887Sdim } 1209218887Sdim } 1210218887Sdim} 1211218887Sdim 1212249423Sdimvoid MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, 1213249423Sdim SourceRange Range, 1214249423Sdim const Expr *DeallocExpr) const { 1215249423Sdim 1216249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 1217249423Sdim !Filter.CNewDeleteChecker) 1218249423Sdim return; 1219249423Sdim 1220251662Sdim if (!isTrackedByCurrentChecker(C, DeallocExpr)) 1221249423Sdim return; 1222249423Sdim 1223218887Sdim if (ExplodedNode *N = C.generateSink()) { 1224218887Sdim if (!BT_BadFree) 1225234353Sdim BT_BadFree.reset(new BugType("Bad free", "Memory Error")); 1226218887Sdim 1227234353Sdim SmallString<100> buf; 1228218887Sdim llvm::raw_svector_ostream os(buf); 1229249423Sdim 1230218887Sdim const MemRegion *MR = ArgVal.getAsRegion(); 1231249423Sdim while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR)) 1232249423Sdim MR = ER->getSuperRegion(); 1233249423Sdim 1234249423Sdim if (MR && isa<AllocaRegion>(MR)) 1235249423Sdim os << "Memory allocated by alloca() should not be deallocated"; 1236249423Sdim else { 1237249423Sdim os << "Argument to "; 1238249423Sdim if (!printAllocDeallocName(os, C, DeallocExpr)) 1239249423Sdim os << "deallocator"; 1240249423Sdim 1241249423Sdim os << " is "; 1242249423Sdim bool Summarized = MR ? SummarizeRegion(os, MR) 1243249423Sdim : SummarizeValue(os, ArgVal); 1244249423Sdim if (Summarized) 1245249423Sdim os << ", which is not memory allocated by "; 1246218887Sdim else 1247249423Sdim os << "not memory allocated by "; 1248249423Sdim 1249249423Sdim printExpectedAllocName(os, C, DeallocExpr); 1250218887Sdim } 1251249423Sdim 1252226633Sdim BugReport *R = new BugReport(*BT_BadFree, os.str(), N); 1253234353Sdim R->markInteresting(MR); 1254249423Sdim R->addRange(Range); 1255243830Sdim C.emitReport(R); 1256218887Sdim } 1257218887Sdim} 1258218887Sdim 1259249423Sdimvoid MallocChecker::ReportMismatchedDealloc(CheckerContext &C, 1260249423Sdim SourceRange Range, 1261249423Sdim const Expr *DeallocExpr, 1262251662Sdim const RefState *RS, 1263263508Sdim SymbolRef Sym, 1264263508Sdim bool OwnershipTransferred) const { 1265249423Sdim 1266249423Sdim if (!Filter.CMismatchedDeallocatorChecker) 1267249423Sdim return; 1268249423Sdim 1269249423Sdim if (ExplodedNode *N = C.generateSink()) { 1270249423Sdim if (!BT_MismatchedDealloc) 1271249423Sdim BT_MismatchedDealloc.reset(new BugType("Bad deallocator", 1272249423Sdim "Memory Error")); 1273249423Sdim 1274249423Sdim SmallString<100> buf; 1275249423Sdim llvm::raw_svector_ostream os(buf); 1276249423Sdim 1277249423Sdim const Expr *AllocExpr = cast<Expr>(RS->getStmt()); 1278249423Sdim SmallString<20> AllocBuf; 1279249423Sdim llvm::raw_svector_ostream AllocOs(AllocBuf); 1280249423Sdim SmallString<20> DeallocBuf; 1281249423Sdim llvm::raw_svector_ostream DeallocOs(DeallocBuf); 1282249423Sdim 1283263508Sdim if (OwnershipTransferred) { 1284263508Sdim if (printAllocDeallocName(DeallocOs, C, DeallocExpr)) 1285263508Sdim os << DeallocOs.str() << " cannot"; 1286263508Sdim else 1287263508Sdim os << "Cannot"; 1288249423Sdim 1289263508Sdim os << " take ownership of memory"; 1290249423Sdim 1291263508Sdim if (printAllocDeallocName(AllocOs, C, AllocExpr)) 1292263508Sdim os << " allocated by " << AllocOs.str(); 1293263508Sdim } else { 1294263508Sdim os << "Memory"; 1295263508Sdim if (printAllocDeallocName(AllocOs, C, AllocExpr)) 1296263508Sdim os << " allocated by " << AllocOs.str(); 1297249423Sdim 1298263508Sdim os << " should be deallocated by "; 1299263508Sdim printExpectedDeallocName(os, RS->getAllocationFamily()); 1300263508Sdim 1301263508Sdim if (printAllocDeallocName(DeallocOs, C, DeallocExpr)) 1302263508Sdim os << ", not " << DeallocOs.str(); 1303263508Sdim } 1304263508Sdim 1305249423Sdim BugReport *R = new BugReport(*BT_MismatchedDealloc, os.str(), N); 1306251662Sdim R->markInteresting(Sym); 1307249423Sdim R->addRange(Range); 1308251662Sdim R->addVisitor(new MallocBugVisitor(Sym)); 1309249423Sdim C.emitReport(R); 1310249423Sdim } 1311249423Sdim} 1312249423Sdim 1313249423Sdimvoid MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal, 1314249423Sdim SourceRange Range, const Expr *DeallocExpr, 1315249423Sdim const Expr *AllocExpr) const { 1316249423Sdim 1317249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 1318249423Sdim !Filter.CNewDeleteChecker) 1319249423Sdim return; 1320249423Sdim 1321251662Sdim if (!isTrackedByCurrentChecker(C, AllocExpr)) 1322249423Sdim return; 1323249423Sdim 1324249423Sdim ExplodedNode *N = C.generateSink(); 1325249423Sdim if (N == NULL) 1326249423Sdim return; 1327249423Sdim 1328249423Sdim if (!BT_OffsetFree) 1329249423Sdim BT_OffsetFree.reset(new BugType("Offset free", "Memory Error")); 1330249423Sdim 1331249423Sdim SmallString<100> buf; 1332249423Sdim llvm::raw_svector_ostream os(buf); 1333249423Sdim SmallString<20> AllocNameBuf; 1334249423Sdim llvm::raw_svector_ostream AllocNameOs(AllocNameBuf); 1335249423Sdim 1336249423Sdim const MemRegion *MR = ArgVal.getAsRegion(); 1337249423Sdim assert(MR && "Only MemRegion based symbols can have offset free errors"); 1338249423Sdim 1339249423Sdim RegionOffset Offset = MR->getAsOffset(); 1340249423Sdim assert((Offset.isValid() && 1341249423Sdim !Offset.hasSymbolicOffset() && 1342249423Sdim Offset.getOffset() != 0) && 1343249423Sdim "Only symbols with a valid offset can have offset free errors"); 1344249423Sdim 1345249423Sdim int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth(); 1346249423Sdim 1347249423Sdim os << "Argument to "; 1348249423Sdim if (!printAllocDeallocName(os, C, DeallocExpr)) 1349249423Sdim os << "deallocator"; 1350249423Sdim os << " is offset by " 1351249423Sdim << offsetBytes 1352249423Sdim << " " 1353249423Sdim << ((abs(offsetBytes) > 1) ? "bytes" : "byte") 1354249423Sdim << " from the start of "; 1355249423Sdim if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr)) 1356249423Sdim os << "memory allocated by " << AllocNameOs.str(); 1357249423Sdim else 1358249423Sdim os << "allocated memory"; 1359249423Sdim 1360249423Sdim BugReport *R = new BugReport(*BT_OffsetFree, os.str(), N); 1361249423Sdim R->markInteresting(MR->getBaseRegion()); 1362249423Sdim R->addRange(Range); 1363249423Sdim C.emitReport(R); 1364249423Sdim} 1365249423Sdim 1366249423Sdimvoid MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range, 1367249423Sdim SymbolRef Sym) const { 1368249423Sdim 1369249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 1370249423Sdim !Filter.CNewDeleteChecker) 1371249423Sdim return; 1372249423Sdim 1373251662Sdim if (!isTrackedByCurrentChecker(C, Sym)) 1374249423Sdim return; 1375249423Sdim 1376249423Sdim if (ExplodedNode *N = C.generateSink()) { 1377249423Sdim if (!BT_UseFree) 1378249423Sdim BT_UseFree.reset(new BugType("Use-after-free", "Memory Error")); 1379249423Sdim 1380249423Sdim BugReport *R = new BugReport(*BT_UseFree, 1381249423Sdim "Use of memory after it is freed", N); 1382249423Sdim 1383249423Sdim R->markInteresting(Sym); 1384249423Sdim R->addRange(Range); 1385249423Sdim R->addVisitor(new MallocBugVisitor(Sym)); 1386249423Sdim C.emitReport(R); 1387249423Sdim } 1388249423Sdim} 1389249423Sdim 1390249423Sdimvoid MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range, 1391249423Sdim bool Released, SymbolRef Sym, 1392249423Sdim SymbolRef PrevSym) const { 1393249423Sdim 1394249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 1395249423Sdim !Filter.CNewDeleteChecker) 1396249423Sdim return; 1397249423Sdim 1398251662Sdim if (!isTrackedByCurrentChecker(C, Sym)) 1399249423Sdim return; 1400249423Sdim 1401249423Sdim if (ExplodedNode *N = C.generateSink()) { 1402249423Sdim if (!BT_DoubleFree) 1403249423Sdim BT_DoubleFree.reset(new BugType("Double free", "Memory Error")); 1404249423Sdim 1405249423Sdim BugReport *R = new BugReport(*BT_DoubleFree, 1406249423Sdim (Released ? "Attempt to free released memory" 1407249423Sdim : "Attempt to free non-owned memory"), 1408249423Sdim N); 1409249423Sdim R->addRange(Range); 1410249423Sdim R->markInteresting(Sym); 1411249423Sdim if (PrevSym) 1412249423Sdim R->markInteresting(PrevSym); 1413249423Sdim R->addVisitor(new MallocBugVisitor(Sym)); 1414249423Sdim C.emitReport(R); 1415249423Sdim } 1416249423Sdim} 1417249423Sdim 1418234353SdimProgramStateRef MallocChecker::ReallocMem(CheckerContext &C, 1419234353Sdim const CallExpr *CE, 1420234353Sdim bool FreesOnFail) const { 1421234353Sdim if (CE->getNumArgs() < 2) 1422234353Sdim return 0; 1423234353Sdim 1424234353Sdim ProgramStateRef state = C.getState(); 1425218887Sdim const Expr *arg0Expr = CE->getArg(0); 1426234353Sdim const LocationContext *LCtx = C.getLocationContext(); 1427234353Sdim SVal Arg0Val = state->getSVal(arg0Expr, LCtx); 1428249423Sdim if (!Arg0Val.getAs<DefinedOrUnknownSVal>()) 1429234353Sdim return 0; 1430249423Sdim DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>(); 1431218887Sdim 1432218887Sdim SValBuilder &svalBuilder = C.getSValBuilder(); 1433218887Sdim 1434218887Sdim DefinedOrUnknownSVal PtrEQ = 1435218887Sdim svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull()); 1436218887Sdim 1437221345Sdim // Get the size argument. If there is no size arg then give up. 1438221345Sdim const Expr *Arg1 = CE->getArg(1); 1439221345Sdim if (!Arg1) 1440234353Sdim return 0; 1441221345Sdim 1442221345Sdim // Get the value of the size argument. 1443234353Sdim SVal Arg1ValG = state->getSVal(Arg1, LCtx); 1444249423Sdim if (!Arg1ValG.getAs<DefinedOrUnknownSVal>()) 1445234353Sdim return 0; 1446249423Sdim DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>(); 1447221345Sdim 1448221345Sdim // Compare the size argument to 0. 1449221345Sdim DefinedOrUnknownSVal SizeZero = 1450221345Sdim svalBuilder.evalEQ(state, Arg1Val, 1451221345Sdim svalBuilder.makeIntValWithPtrWidth(0, false)); 1452221345Sdim 1453234353Sdim ProgramStateRef StatePtrIsNull, StatePtrNotNull; 1454234353Sdim llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ); 1455234353Sdim ProgramStateRef StateSizeIsZero, StateSizeNotZero; 1456234353Sdim llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero); 1457234353Sdim // We only assume exceptional states if they are definitely true; if the 1458234353Sdim // state is under-constrained, assume regular realloc behavior. 1459234353Sdim bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull; 1460234353Sdim bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero; 1461234353Sdim 1462221345Sdim // If the ptr is NULL and the size is not 0, the call is equivalent to 1463221345Sdim // malloc(size). 1464234353Sdim if ( PrtIsNull && !SizeIsZero) { 1465234353Sdim ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1), 1466234353Sdim UndefinedVal(), StatePtrIsNull); 1467234353Sdim return stateMalloc; 1468218887Sdim } 1469218887Sdim 1470234353Sdim if (PrtIsNull && SizeIsZero) 1471234353Sdim return 0; 1472218887Sdim 1473234353Sdim // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size). 1474234353Sdim assert(!PrtIsNull); 1475234353Sdim SymbolRef FromPtr = arg0Val.getAsSymbol(); 1476234353Sdim SVal RetVal = state->getSVal(CE, LCtx); 1477234353Sdim SymbolRef ToPtr = RetVal.getAsSymbol(); 1478234353Sdim if (!FromPtr || !ToPtr) 1479234353Sdim return 0; 1480234353Sdim 1481243830Sdim bool ReleasedAllocated = false; 1482243830Sdim 1483234353Sdim // If the size is 0, free the memory. 1484234353Sdim if (SizeIsZero) 1485243830Sdim if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0, 1486243830Sdim false, ReleasedAllocated)){ 1487234353Sdim // The semantics of the return value are: 1488234353Sdim // If size was equal to 0, either NULL or a pointer suitable to be passed 1489239462Sdim // to free() is returned. We just free the input pointer and do not add 1490239462Sdim // any constrains on the output pointer. 1491234353Sdim return stateFree; 1492234353Sdim } 1493234353Sdim 1494234353Sdim // Default behavior. 1495243830Sdim if (ProgramStateRef stateFree = 1496243830Sdim FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) { 1497243830Sdim 1498234353Sdim ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 1499234353Sdim UnknownVal(), stateFree); 1500234353Sdim if (!stateRealloc) 1501234353Sdim return 0; 1502243830Sdim 1503243830Sdim ReallocPairKind Kind = RPToBeFreedAfterFailure; 1504243830Sdim if (FreesOnFail) 1505243830Sdim Kind = RPIsFreeOnFailure; 1506243830Sdim else if (!ReleasedAllocated) 1507243830Sdim Kind = RPDoNotTrackAfterFailure; 1508243830Sdim 1509243830Sdim // Record the info about the reallocated symbol so that we could properly 1510243830Sdim // process failed reallocation. 1511234353Sdim stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr, 1512243830Sdim ReallocPair(FromPtr, Kind)); 1513243830Sdim // The reallocated symbol should stay alive for as long as the new symbol. 1514234353Sdim C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr); 1515234353Sdim return stateRealloc; 1516218887Sdim } 1517234353Sdim return 0; 1518218887Sdim} 1519218887Sdim 1520234353SdimProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){ 1521234353Sdim if (CE->getNumArgs() < 2) 1522234353Sdim return 0; 1523234353Sdim 1524234353Sdim ProgramStateRef state = C.getState(); 1525218887Sdim SValBuilder &svalBuilder = C.getSValBuilder(); 1526234353Sdim const LocationContext *LCtx = C.getLocationContext(); 1527234353Sdim SVal count = state->getSVal(CE->getArg(0), LCtx); 1528234353Sdim SVal elementSize = state->getSVal(CE->getArg(1), LCtx); 1529218887Sdim SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize, 1530218887Sdim svalBuilder.getContext().getSizeType()); 1531218887Sdim SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); 1532218887Sdim 1533234353Sdim return MallocMemAux(C, CE, TotalSize, zeroVal, state); 1534218887Sdim} 1535218887Sdim 1536234353SdimLeakInfo 1537234353SdimMallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, 1538234353Sdim CheckerContext &C) const { 1539234353Sdim const LocationContext *LeakContext = N->getLocationContext(); 1540234353Sdim // Walk the ExplodedGraph backwards and find the first node that referred to 1541234353Sdim // the tracked symbol. 1542234353Sdim const ExplodedNode *AllocNode = N; 1543234353Sdim const MemRegion *ReferenceRegion = 0; 1544234353Sdim 1545234353Sdim while (N) { 1546234353Sdim ProgramStateRef State = N->getState(); 1547234353Sdim if (!State->get<RegionState>(Sym)) 1548234353Sdim break; 1549234353Sdim 1550234353Sdim // Find the most recent expression bound to the symbol in the current 1551234353Sdim // context. 1552251662Sdim if (!ReferenceRegion) { 1553251662Sdim if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) { 1554251662Sdim SVal Val = State->getSVal(MR); 1555251662Sdim if (Val.getAsLocSymbol() == Sym) { 1556251662Sdim const VarRegion* VR = MR->getBaseRegion()->getAs<VarRegion>(); 1557251662Sdim // Do not show local variables belonging to a function other than 1558251662Sdim // where the error is reported. 1559251662Sdim if (!VR || 1560251662Sdim (VR->getStackFrame() == LeakContext->getCurrentStackFrame())) 1561251662Sdim ReferenceRegion = MR; 1562251662Sdim } 1563251662Sdim } 1564234353Sdim } 1565234353Sdim 1566234353Sdim // Allocation node, is the last node in the current context in which the 1567234353Sdim // symbol was tracked. 1568234353Sdim if (N->getLocationContext() == LeakContext) 1569234353Sdim AllocNode = N; 1570234353Sdim N = N->pred_empty() ? NULL : *(N->pred_begin()); 1571234353Sdim } 1572234353Sdim 1573249423Sdim return LeakInfo(AllocNode, ReferenceRegion); 1574234353Sdim} 1575234353Sdim 1576234353Sdimvoid MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, 1577234353Sdim CheckerContext &C) const { 1578249423Sdim 1579249423Sdim if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic && 1580251662Sdim !Filter.CNewDeleteLeaksChecker) 1581249423Sdim return; 1582249423Sdim 1583251662Sdim const RefState *RS = C.getState()->get<RegionState>(Sym); 1584251662Sdim assert(RS && "cannot leak an untracked symbol"); 1585251662Sdim AllocationFamily Family = RS->getAllocationFamily(); 1586251662Sdim if (!isTrackedByCurrentChecker(Family)) 1587249423Sdim return; 1588249423Sdim 1589251662Sdim // Special case for new and new[]; these are controlled by a separate checker 1590251662Sdim // flag so that they can be selectively disabled. 1591251662Sdim if (Family == AF_CXXNew || Family == AF_CXXNewArray) 1592251662Sdim if (!Filter.CNewDeleteLeaksChecker) 1593251662Sdim return; 1594251662Sdim 1595234353Sdim assert(N); 1596234353Sdim if (!BT_Leak) { 1597234353Sdim BT_Leak.reset(new BugType("Memory leak", "Memory Error")); 1598234353Sdim // Leaks should not be reported if they are post-dominated by a sink: 1599234353Sdim // (1) Sinks are higher importance bugs. 1600234353Sdim // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending 1601234353Sdim // with __noreturn functions such as assert() or exit(). We choose not 1602234353Sdim // to report leaks on such paths. 1603234353Sdim BT_Leak->setSuppressOnSink(true); 1604234353Sdim } 1605234353Sdim 1606234353Sdim // Most bug reports are cached at the location where they occurred. 1607234353Sdim // With leaks, we want to unique them by the location where they were 1608234353Sdim // allocated, and only report a single path. 1609234353Sdim PathDiagnosticLocation LocUsedForUniqueing; 1610249423Sdim const ExplodedNode *AllocNode = 0; 1611234353Sdim const MemRegion *Region = 0; 1612249423Sdim llvm::tie(AllocNode, Region) = getAllocationSite(N, Sym, C); 1613249423Sdim 1614249423Sdim ProgramPoint P = AllocNode->getLocation(); 1615249423Sdim const Stmt *AllocationStmt = 0; 1616249423Sdim if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>()) 1617249423Sdim AllocationStmt = Exit->getCalleeContext()->getCallSite(); 1618249423Sdim else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) 1619249423Sdim AllocationStmt = SP->getStmt(); 1620249423Sdim if (AllocationStmt) 1621249423Sdim LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt, 1622249423Sdim C.getSourceManager(), 1623249423Sdim AllocNode->getLocationContext()); 1624234353Sdim 1625234353Sdim SmallString<200> buf; 1626234353Sdim llvm::raw_svector_ostream os(buf); 1627239462Sdim if (Region && Region->canPrintPretty()) { 1628251662Sdim os << "Potential leak of memory pointed to by "; 1629239462Sdim Region->printPretty(os); 1630251662Sdim } else { 1631251662Sdim os << "Potential memory leak"; 1632234353Sdim } 1633234353Sdim 1634249423Sdim BugReport *R = new BugReport(*BT_Leak, os.str(), N, 1635249423Sdim LocUsedForUniqueing, 1636249423Sdim AllocNode->getLocationContext()->getDecl()); 1637234353Sdim R->markInteresting(Sym); 1638239462Sdim R->addVisitor(new MallocBugVisitor(Sym, true)); 1639243830Sdim C.emitReport(R); 1640234353Sdim} 1641234353Sdim 1642221345Sdimvoid MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, 1643221345Sdim CheckerContext &C) const 1644218887Sdim{ 1645218887Sdim if (!SymReaper.hasDeadSymbols()) 1646218887Sdim return; 1647218887Sdim 1648234353Sdim ProgramStateRef state = C.getState(); 1649218887Sdim RegionStateTy RS = state->get<RegionState>(); 1650218887Sdim RegionStateTy::Factory &F = state->get_context<RegionState>(); 1651218887Sdim 1652249423Sdim SmallVector<SymbolRef, 2> Errors; 1653218887Sdim for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 1654218887Sdim if (SymReaper.isDead(I->first)) { 1655243830Sdim if (I->second.isAllocated()) 1656234353Sdim Errors.push_back(I->first); 1657218887Sdim // Remove the dead symbol from the map. 1658218887Sdim RS = F.remove(RS, I->first); 1659226633Sdim 1660218887Sdim } 1661218887Sdim } 1662226633Sdim 1663234353Sdim // Cleanup the Realloc Pairs Map. 1664243830Sdim ReallocPairsTy RP = state->get<ReallocPairs>(); 1665243830Sdim for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 1666234353Sdim if (SymReaper.isDead(I->first) || 1667234353Sdim SymReaper.isDead(I->second.ReallocatedSym)) { 1668234353Sdim state = state->remove<ReallocPairs>(I->first); 1669234353Sdim } 1670234353Sdim } 1671226633Sdim 1672243830Sdim // Cleanup the FreeReturnValue Map. 1673243830Sdim FreeReturnValueTy FR = state->get<FreeReturnValue>(); 1674243830Sdim for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) { 1675243830Sdim if (SymReaper.isDead(I->first) || 1676243830Sdim SymReaper.isDead(I->second)) { 1677243830Sdim state = state->remove<FreeReturnValue>(I->first); 1678243830Sdim } 1679243830Sdim } 1680243830Sdim 1681234353Sdim // Generate leak node. 1682243830Sdim ExplodedNode *N = C.getPredecessor(); 1683243830Sdim if (!Errors.empty()) { 1684243830Sdim static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak"); 1685243830Sdim N = C.addTransition(C.getState(), C.getPredecessor(), &Tag); 1686263508Sdim for (SmallVectorImpl<SymbolRef>::iterator 1687263508Sdim I = Errors.begin(), E = Errors.end(); I != E; ++I) { 1688234353Sdim reportLeak(*I, N, C); 1689234353Sdim } 1690226633Sdim } 1691243830Sdim 1692234353Sdim C.addTransition(state->set<RegionState>(RS), N); 1693218887Sdim} 1694218887Sdim 1695251662Sdimvoid MallocChecker::checkPreCall(const CallEvent &Call, 1696251662Sdim CheckerContext &C) const { 1697251662Sdim 1698239462Sdim // We will check for double free in the post visit. 1699251662Sdim if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) { 1700251662Sdim const FunctionDecl *FD = FC->getDecl(); 1701251662Sdim if (!FD) 1702251662Sdim return; 1703234353Sdim 1704251662Sdim if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) && 1705251662Sdim isFreeFunction(FD, C.getASTContext())) 1706251662Sdim return; 1707249423Sdim 1708251662Sdim if (Filter.CNewDeleteChecker && 1709251662Sdim isStandardNewDelete(FD, C.getASTContext())) 1710251662Sdim return; 1711251662Sdim } 1712251662Sdim 1713251662Sdim // Check if the callee of a method is deleted. 1714251662Sdim if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) { 1715251662Sdim SymbolRef Sym = CC->getCXXThisVal().getAsSymbol(); 1716251662Sdim if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr())) 1717251662Sdim return; 1718251662Sdim } 1719251662Sdim 1720251662Sdim // Check arguments for being used after free. 1721251662Sdim for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) { 1722251662Sdim SVal ArgSVal = Call.getArgSVal(I); 1723251662Sdim if (ArgSVal.getAs<Loc>()) { 1724251662Sdim SymbolRef Sym = ArgSVal.getAsSymbol(); 1725234353Sdim if (!Sym) 1726234353Sdim continue; 1727251662Sdim if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) 1728234353Sdim return; 1729234353Sdim } 1730234353Sdim } 1731234353Sdim} 1732234353Sdim 1733221345Sdimvoid MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { 1734234353Sdim const Expr *E = S->getRetValue(); 1735234353Sdim if (!E) 1736218887Sdim return; 1737218887Sdim 1738234353Sdim // Check if we are returning a symbol. 1739239462Sdim ProgramStateRef State = C.getState(); 1740239462Sdim SVal RetVal = State->getSVal(E, C.getLocationContext()); 1741234353Sdim SymbolRef Sym = RetVal.getAsSymbol(); 1742218887Sdim if (!Sym) 1743234353Sdim // If we are returning a field of the allocated struct or an array element, 1744234353Sdim // the callee could still free the memory. 1745234353Sdim // TODO: This logic should be a part of generic symbol escape callback. 1746234353Sdim if (const MemRegion *MR = RetVal.getAsRegion()) 1747234353Sdim if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR)) 1748234353Sdim if (const SymbolicRegion *BMR = 1749234353Sdim dyn_cast<SymbolicRegion>(MR->getBaseRegion())) 1750234353Sdim Sym = BMR->getSymbol(); 1751218887Sdim 1752234353Sdim // Check if we are returning freed memory. 1753239462Sdim if (Sym) 1754249423Sdim checkUseAfterFree(Sym, C, E); 1755218887Sdim} 1756218887Sdim 1757234353Sdim// TODO: Blocks should be either inlined or should call invalidate regions 1758234353Sdim// upon invocation. After that's in place, special casing here will not be 1759234353Sdim// needed. 1760234353Sdimvoid MallocChecker::checkPostStmt(const BlockExpr *BE, 1761234353Sdim CheckerContext &C) const { 1762218887Sdim 1763234353Sdim // Scan the BlockDecRefExprs for any object the retain count checker 1764234353Sdim // may be tracking. 1765234353Sdim if (!BE->getBlockDecl()->hasCaptures()) 1766234353Sdim return; 1767218887Sdim 1768234353Sdim ProgramStateRef state = C.getState(); 1769234353Sdim const BlockDataRegion *R = 1770234353Sdim cast<BlockDataRegion>(state->getSVal(BE, 1771234353Sdim C.getLocationContext()).getAsRegion()); 1772234353Sdim 1773234353Sdim BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), 1774234353Sdim E = R->referenced_vars_end(); 1775234353Sdim 1776234353Sdim if (I == E) 1777234353Sdim return; 1778234353Sdim 1779234353Sdim SmallVector<const MemRegion*, 10> Regions; 1780234353Sdim const LocationContext *LC = C.getLocationContext(); 1781234353Sdim MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager(); 1782234353Sdim 1783234353Sdim for ( ; I != E; ++I) { 1784249423Sdim const VarRegion *VR = I.getCapturedRegion(); 1785234353Sdim if (VR->getSuperRegion() == R) { 1786234353Sdim VR = MemMgr.getVarRegion(VR->getDecl(), LC); 1787234353Sdim } 1788234353Sdim Regions.push_back(VR); 1789218887Sdim } 1790218887Sdim 1791234353Sdim state = 1792234353Sdim state->scanReachableSymbols<StopTrackingCallback>(Regions.data(), 1793234353Sdim Regions.data() + Regions.size()).getState(); 1794234353Sdim C.addTransition(state); 1795218887Sdim} 1796218887Sdim 1797239462Sdimbool MallocChecker::isReleased(SymbolRef Sym, CheckerContext &C) const { 1798239462Sdim assert(Sym); 1799239462Sdim const RefState *RS = C.getState()->get<RegionState>(Sym); 1800239462Sdim return (RS && RS->isReleased()); 1801239462Sdim} 1802239462Sdim 1803234353Sdimbool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, 1804234353Sdim const Stmt *S) const { 1805249423Sdim 1806263508Sdim // FIXME: Handle destructor called from delete more precisely. 1807263508Sdim if (isReleased(Sym, C) && S) { 1808249423Sdim ReportUseAfterFree(C, S->getSourceRange(), Sym); 1809249423Sdim return true; 1810249423Sdim } 1811234353Sdim 1812234353Sdim return false; 1813234353Sdim} 1814234353Sdim 1815218887Sdim// Check if the location is a freed symbolic region. 1816226633Sdimvoid MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S, 1817226633Sdim CheckerContext &C) const { 1818218887Sdim SymbolRef Sym = l.getLocSymbolInBase(); 1819234353Sdim if (Sym) 1820239462Sdim checkUseAfterFree(Sym, C, S); 1821234353Sdim} 1822218887Sdim 1823234353Sdim// If a symbolic region is assumed to NULL (or another constant), stop tracking 1824234353Sdim// it - assuming that allocation failed on this path. 1825234353SdimProgramStateRef MallocChecker::evalAssume(ProgramStateRef state, 1826234353Sdim SVal Cond, 1827234353Sdim bool Assumption) const { 1828234353Sdim RegionStateTy RS = state->get<RegionState>(); 1829234353Sdim for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 1830243830Sdim // If the symbol is assumed to be NULL, remove it from consideration. 1831243830Sdim ConstraintManager &CMgr = state->getConstraintManager(); 1832243830Sdim ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey()); 1833243830Sdim if (AllocFailed.isConstrainedTrue()) 1834234353Sdim state = state->remove<RegionState>(I.getKey()); 1835234353Sdim } 1836234353Sdim 1837234353Sdim // Realloc returns 0 when reallocation fails, which means that we should 1838234353Sdim // restore the state of the pointer being reallocated. 1839243830Sdim ReallocPairsTy RP = state->get<ReallocPairs>(); 1840243830Sdim for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 1841243830Sdim // If the symbol is assumed to be NULL, remove it from consideration. 1842243830Sdim ConstraintManager &CMgr = state->getConstraintManager(); 1843243830Sdim ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey()); 1844243830Sdim if (!AllocFailed.isConstrainedTrue()) 1845243830Sdim continue; 1846243830Sdim 1847243830Sdim SymbolRef ReallocSym = I.getData().ReallocatedSym; 1848243830Sdim if (const RefState *RS = state->get<RegionState>(ReallocSym)) { 1849243830Sdim if (RS->isReleased()) { 1850243830Sdim if (I.getData().Kind == RPToBeFreedAfterFailure) 1851234353Sdim state = state->set<RegionState>(ReallocSym, 1852249423Sdim RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt())); 1853243830Sdim else if (I.getData().Kind == RPDoNotTrackAfterFailure) 1854243830Sdim state = state->remove<RegionState>(ReallocSym); 1855243830Sdim else 1856243830Sdim assert(I.getData().Kind == RPIsFreeOnFailure); 1857218887Sdim } 1858218887Sdim } 1859243830Sdim state = state->remove<ReallocPairs>(I.getKey()); 1860218887Sdim } 1861234353Sdim 1862234353Sdim return state; 1863218887Sdim} 1864218887Sdim 1865263508Sdimbool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly( 1866263508Sdim const CallEvent *Call, 1867263508Sdim ProgramStateRef State, 1868263508Sdim SymbolRef &EscapingSymbol) const { 1869239462Sdim assert(Call); 1870263508Sdim EscapingSymbol = 0; 1871263508Sdim 1872234353Sdim // For now, assume that any C++ call can free memory. 1873234353Sdim // TODO: If we want to be more optimistic here, we'll need to make sure that 1874234353Sdim // regions escape to C++ containers. They seem to do that even now, but for 1875234353Sdim // mysterious reasons. 1876239462Sdim if (!(isa<FunctionCall>(Call) || isa<ObjCMethodCall>(Call))) 1877263508Sdim return true; 1878218887Sdim 1879239462Sdim // Check Objective-C messages by selector name. 1880239462Sdim if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) { 1881239462Sdim // If it's not a framework call, or if it takes a callback, assume it 1882239462Sdim // can free memory. 1883239462Sdim if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg()) 1884263508Sdim return true; 1885218887Sdim 1886249423Sdim // If it's a method we know about, handle it explicitly post-call. 1887249423Sdim // This should happen before the "freeWhenDone" check below. 1888249423Sdim if (isKnownDeallocObjCMethodName(*Msg)) 1889263508Sdim return false; 1890234353Sdim 1891249423Sdim // If there's a "freeWhenDone" parameter, but the method isn't one we know 1892249423Sdim // about, we can't be sure that the object will use free() to deallocate the 1893249423Sdim // memory, so we can't model it explicitly. The best we can do is use it to 1894249423Sdim // decide whether the pointer escapes. 1895249423Sdim if (Optional<bool> FreeWhenDone = getFreeWhenDoneArg(*Msg)) 1896263508Sdim return *FreeWhenDone; 1897234353Sdim 1898249423Sdim // If the first selector piece ends with "NoCopy", and there is no 1899249423Sdim // "freeWhenDone" parameter set to zero, we know ownership is being 1900249423Sdim // transferred. Again, though, we can't be sure that the object will use 1901249423Sdim // free() to deallocate the memory, so we can't model it explicitly. 1902249423Sdim StringRef FirstSlot = Msg->getSelector().getNameForSlot(0); 1903239462Sdim if (FirstSlot.endswith("NoCopy")) 1904263508Sdim return true; 1905239462Sdim 1906239462Sdim // If the first selector starts with addPointer, insertPointer, 1907239462Sdim // or replacePointer, assume we are dealing with NSPointerArray or similar. 1908239462Sdim // This is similar to C++ containers (vector); we still might want to check 1909239462Sdim // that the pointers get freed by following the container itself. 1910239462Sdim if (FirstSlot.startswith("addPointer") || 1911239462Sdim FirstSlot.startswith("insertPointer") || 1912239462Sdim FirstSlot.startswith("replacePointer")) { 1913263508Sdim return true; 1914234353Sdim } 1915234353Sdim 1916263508Sdim // We should escape receiver on call to 'init'. This is especially relevant 1917263508Sdim // to the receiver, as the corresponding symbol is usually not referenced 1918263508Sdim // after the call. 1919263508Sdim if (Msg->getMethodFamily() == OMF_init) { 1920263508Sdim EscapingSymbol = Msg->getReceiverSVal().getAsSymbol(); 1921263508Sdim return true; 1922263508Sdim } 1923263508Sdim 1924239462Sdim // Otherwise, assume that the method does not free memory. 1925239462Sdim // Most framework methods do not free memory. 1926263508Sdim return false; 1927218887Sdim } 1928234353Sdim 1929239462Sdim // At this point the only thing left to handle is straight function calls. 1930239462Sdim const FunctionDecl *FD = cast<FunctionCall>(Call)->getDecl(); 1931239462Sdim if (!FD) 1932263508Sdim return true; 1933234353Sdim 1934239462Sdim ASTContext &ASTC = State->getStateManager().getContext(); 1935239462Sdim 1936239462Sdim // If it's one of the allocation functions we can reason about, we model 1937239462Sdim // its behavior explicitly. 1938239462Sdim if (isMemFunction(FD, ASTC)) 1939263508Sdim return false; 1940239462Sdim 1941239462Sdim // If it's not a system call, assume it frees memory. 1942239462Sdim if (!Call->isInSystemHeader()) 1943263508Sdim return true; 1944239462Sdim 1945239462Sdim // White list the system functions whose arguments escape. 1946239462Sdim const IdentifierInfo *II = FD->getIdentifier(); 1947239462Sdim if (!II) 1948263508Sdim return true; 1949239462Sdim StringRef FName = II->getName(); 1950239462Sdim 1951239462Sdim // White list the 'XXXNoCopy' CoreFoundation functions. 1952239462Sdim // We specifically check these before 1953239462Sdim if (FName.endswith("NoCopy")) { 1954239462Sdim // Look for the deallocator argument. We know that the memory ownership 1955239462Sdim // is not transferred only if the deallocator argument is 1956239462Sdim // 'kCFAllocatorNull'. 1957239462Sdim for (unsigned i = 1; i < Call->getNumArgs(); ++i) { 1958239462Sdim const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts(); 1959239462Sdim if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) { 1960239462Sdim StringRef DeallocatorName = DE->getFoundDecl()->getName(); 1961239462Sdim if (DeallocatorName == "kCFAllocatorNull") 1962263508Sdim return false; 1963239462Sdim } 1964239462Sdim } 1965263508Sdim return true; 1966239462Sdim } 1967239462Sdim 1968239462Sdim // Associating streams with malloced buffers. The pointer can escape if 1969239462Sdim // 'closefn' is specified (and if that function does free memory), 1970239462Sdim // but it will not if closefn is not specified. 1971239462Sdim // Currently, we do not inspect the 'closefn' function (PR12101). 1972239462Sdim if (FName == "funopen") 1973239462Sdim if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0)) 1974263508Sdim return false; 1975239462Sdim 1976239462Sdim // Do not warn on pointers passed to 'setbuf' when used with std streams, 1977239462Sdim // these leaks might be intentional when setting the buffer for stdio. 1978239462Sdim // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer 1979239462Sdim if (FName == "setbuf" || FName =="setbuffer" || 1980239462Sdim FName == "setlinebuf" || FName == "setvbuf") { 1981239462Sdim if (Call->getNumArgs() >= 1) { 1982239462Sdim const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts(); 1983239462Sdim if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE)) 1984239462Sdim if (const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl())) 1985239462Sdim if (D->getCanonicalDecl()->getName().find("std") != StringRef::npos) 1986263508Sdim return true; 1987239462Sdim } 1988239462Sdim } 1989239462Sdim 1990239462Sdim // A bunch of other functions which either take ownership of a pointer or 1991239462Sdim // wrap the result up in a struct or object, meaning it can be freed later. 1992239462Sdim // (See RetainCountChecker.) Not all the parameters here are invalidated, 1993239462Sdim // but the Malloc checker cannot differentiate between them. The right way 1994239462Sdim // of doing this would be to implement a pointer escapes callback. 1995239462Sdim if (FName == "CGBitmapContextCreate" || 1996239462Sdim FName == "CGBitmapContextCreateWithData" || 1997239462Sdim FName == "CVPixelBufferCreateWithBytes" || 1998239462Sdim FName == "CVPixelBufferCreateWithPlanarBytes" || 1999239462Sdim FName == "OSAtomicEnqueue") { 2000263508Sdim return true; 2001239462Sdim } 2002239462Sdim 2003239462Sdim // Handle cases where we know a buffer's /address/ can escape. 2004239462Sdim // Note that the above checks handle some special cases where we know that 2005239462Sdim // even though the address escapes, it's still our responsibility to free the 2006239462Sdim // buffer. 2007239462Sdim if (Call->argumentsMayEscape()) 2008263508Sdim return true; 2009239462Sdim 2010239462Sdim // Otherwise, assume that the function does not free memory. 2011239462Sdim // Most system calls do not free the memory. 2012263508Sdim return false; 2013218887Sdim} 2014221345Sdim 2015249423Sdimstatic bool retTrue(const RefState *RS) { 2016249423Sdim return true; 2017249423Sdim} 2018234353Sdim 2019249423Sdimstatic bool checkIfNewOrNewArrayFamily(const RefState *RS) { 2020249423Sdim return (RS->getAllocationFamily() == AF_CXXNewArray || 2021249423Sdim RS->getAllocationFamily() == AF_CXXNew); 2022249423Sdim} 2023234353Sdim 2024249423SdimProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State, 2025249423Sdim const InvalidatedSymbols &Escaped, 2026249423Sdim const CallEvent *Call, 2027249423Sdim PointerEscapeKind Kind) const { 2028249423Sdim return checkPointerEscapeAux(State, Escaped, Call, Kind, &retTrue); 2029249423Sdim} 2030249423Sdim 2031249423SdimProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State, 2032249423Sdim const InvalidatedSymbols &Escaped, 2033249423Sdim const CallEvent *Call, 2034249423Sdim PointerEscapeKind Kind) const { 2035249423Sdim return checkPointerEscapeAux(State, Escaped, Call, Kind, 2036249423Sdim &checkIfNewOrNewArrayFamily); 2037249423Sdim} 2038249423Sdim 2039249423SdimProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State, 2040249423Sdim const InvalidatedSymbols &Escaped, 2041249423Sdim const CallEvent *Call, 2042249423Sdim PointerEscapeKind Kind, 2043249423Sdim bool(*CheckRefState)(const RefState*)) const { 2044249423Sdim // If we know that the call does not free memory, or we want to process the 2045249423Sdim // call later, keep tracking the top level arguments. 2046263508Sdim SymbolRef EscapingSymbol = 0; 2047263508Sdim if (Kind == PSK_DirectEscapeOnCall && 2048263508Sdim !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State, 2049263508Sdim EscapingSymbol) && 2050263508Sdim !EscapingSymbol) { 2051249423Sdim return State; 2052234353Sdim } 2053234353Sdim 2054249423Sdim for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 2055249423Sdim E = Escaped.end(); 2056249423Sdim I != E; ++I) { 2057234353Sdim SymbolRef sym = *I; 2058249423Sdim 2059263508Sdim if (EscapingSymbol && EscapingSymbol != sym) 2060263508Sdim continue; 2061263508Sdim 2062239462Sdim if (const RefState *RS = State->get<RegionState>(sym)) { 2063251662Sdim if (RS->isAllocated() && CheckRefState(RS)) { 2064239462Sdim State = State->remove<RegionState>(sym); 2065251662Sdim State = State->set<RegionState>(sym, RefState::getEscaped(RS)); 2066251662Sdim } 2067239462Sdim } 2068234353Sdim } 2069234353Sdim return State; 2070221345Sdim} 2071234353Sdim 2072234353Sdimstatic SymbolRef findFailedReallocSymbol(ProgramStateRef currState, 2073234353Sdim ProgramStateRef prevState) { 2074243830Sdim ReallocPairsTy currMap = currState->get<ReallocPairs>(); 2075243830Sdim ReallocPairsTy prevMap = prevState->get<ReallocPairs>(); 2076234353Sdim 2077243830Sdim for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end(); 2078234353Sdim I != E; ++I) { 2079234353Sdim SymbolRef sym = I.getKey(); 2080234353Sdim if (!currMap.lookup(sym)) 2081234353Sdim return sym; 2082234353Sdim } 2083234353Sdim 2084234353Sdim return NULL; 2085234353Sdim} 2086234353Sdim 2087234353SdimPathDiagnosticPiece * 2088234353SdimMallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, 2089234353Sdim const ExplodedNode *PrevN, 2090234353Sdim BugReporterContext &BRC, 2091234353Sdim BugReport &BR) { 2092234353Sdim ProgramStateRef state = N->getState(); 2093234353Sdim ProgramStateRef statePrev = PrevN->getState(); 2094234353Sdim 2095234353Sdim const RefState *RS = state->get<RegionState>(Sym); 2096234353Sdim const RefState *RSPrev = statePrev->get<RegionState>(Sym); 2097239462Sdim if (!RS) 2098234353Sdim return 0; 2099234353Sdim 2100234353Sdim const Stmt *S = 0; 2101234353Sdim const char *Msg = 0; 2102234353Sdim StackHintGeneratorForSymbol *StackHint = 0; 2103234353Sdim 2104234353Sdim // Retrieve the associated statement. 2105234353Sdim ProgramPoint ProgLoc = N->getLocation(); 2106249423Sdim if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) { 2107239462Sdim S = SP->getStmt(); 2108249423Sdim } else if (Optional<CallExitEnd> Exit = ProgLoc.getAs<CallExitEnd>()) { 2109239462Sdim S = Exit->getCalleeContext()->getCallSite(); 2110249423Sdim } else if (Optional<BlockEdge> Edge = ProgLoc.getAs<BlockEdge>()) { 2111249423Sdim // If an assumption was made on a branch, it should be caught 2112249423Sdim // here by looking at the state transition. 2113249423Sdim S = Edge->getSrc()->getTerminator(); 2114234353Sdim } 2115249423Sdim 2116234353Sdim if (!S) 2117234353Sdim return 0; 2118234353Sdim 2119239462Sdim // FIXME: We will eventually need to handle non-statement-based events 2120239462Sdim // (__attribute__((cleanup))). 2121239462Sdim 2122234353Sdim // Find out if this is an interesting point and what is the kind. 2123234353Sdim if (Mode == Normal) { 2124234353Sdim if (isAllocated(RS, RSPrev, S)) { 2125234353Sdim Msg = "Memory is allocated"; 2126234353Sdim StackHint = new StackHintGeneratorForSymbol(Sym, 2127234353Sdim "Returned allocated memory"); 2128234353Sdim } else if (isReleased(RS, RSPrev, S)) { 2129234353Sdim Msg = "Memory is released"; 2130234353Sdim StackHint = new StackHintGeneratorForSymbol(Sym, 2131251662Sdim "Returning; memory was released"); 2132239462Sdim } else if (isRelinquished(RS, RSPrev, S)) { 2133239462Sdim Msg = "Memory ownership is transfered"; 2134239462Sdim StackHint = new StackHintGeneratorForSymbol(Sym, ""); 2135234353Sdim } else if (isReallocFailedCheck(RS, RSPrev, S)) { 2136234353Sdim Mode = ReallocationFailed; 2137234353Sdim Msg = "Reallocation failed"; 2138234353Sdim StackHint = new StackHintGeneratorForReallocationFailed(Sym, 2139234353Sdim "Reallocation failed"); 2140234353Sdim 2141234353Sdim if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) { 2142234353Sdim // Is it possible to fail two reallocs WITHOUT testing in between? 2143234353Sdim assert((!FailedReallocSymbol || FailedReallocSymbol == sym) && 2144234353Sdim "We only support one failed realloc at a time."); 2145234353Sdim BR.markInteresting(sym); 2146234353Sdim FailedReallocSymbol = sym; 2147234353Sdim } 2148234353Sdim } 2149234353Sdim 2150234353Sdim // We are in a special mode if a reallocation failed later in the path. 2151234353Sdim } else if (Mode == ReallocationFailed) { 2152234353Sdim assert(FailedReallocSymbol && "No symbol to look for."); 2153234353Sdim 2154234353Sdim // Is this is the first appearance of the reallocated symbol? 2155234353Sdim if (!statePrev->get<RegionState>(FailedReallocSymbol)) { 2156234353Sdim // We're at the reallocation point. 2157234353Sdim Msg = "Attempt to reallocate memory"; 2158234353Sdim StackHint = new StackHintGeneratorForSymbol(Sym, 2159234353Sdim "Returned reallocated memory"); 2160234353Sdim FailedReallocSymbol = NULL; 2161234353Sdim Mode = Normal; 2162234353Sdim } 2163234353Sdim } 2164234353Sdim 2165234353Sdim if (!Msg) 2166234353Sdim return 0; 2167234353Sdim assert(StackHint); 2168234353Sdim 2169234353Sdim // Generate the extra diagnostic. 2170234353Sdim PathDiagnosticLocation Pos(S, BRC.getSourceManager(), 2171234353Sdim N->getLocationContext()); 2172234353Sdim return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint); 2173234353Sdim} 2174234353Sdim 2175239462Sdimvoid MallocChecker::printState(raw_ostream &Out, ProgramStateRef State, 2176239462Sdim const char *NL, const char *Sep) const { 2177234353Sdim 2178239462Sdim RegionStateTy RS = State->get<RegionState>(); 2179239462Sdim 2180249423Sdim if (!RS.isEmpty()) { 2181249423Sdim Out << Sep << "MallocChecker:" << NL; 2182249423Sdim for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 2183249423Sdim I.getKey()->dumpToStream(Out); 2184249423Sdim Out << " : "; 2185249423Sdim I.getData().dump(Out); 2186249423Sdim Out << NL; 2187249423Sdim } 2188249423Sdim } 2189239462Sdim} 2190239462Sdim 2191251662Sdimvoid ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) { 2192251662Sdim registerCStringCheckerBasic(mgr); 2193251662Sdim mgr.registerChecker<MallocChecker>()->Filter.CNewDeleteLeaksChecker = true; 2194251662Sdim // We currently treat NewDeleteLeaks checker as a subchecker of NewDelete 2195251662Sdim // checker. 2196251662Sdim mgr.registerChecker<MallocChecker>()->Filter.CNewDeleteChecker = true; 2197251662Sdim} 2198251662Sdim 2199234353Sdim#define REGISTER_CHECKER(name) \ 2200234353Sdimvoid ento::register##name(CheckerManager &mgr) {\ 2201234353Sdim registerCStringCheckerBasic(mgr); \ 2202234353Sdim mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\ 2203234353Sdim} 2204234353Sdim 2205234353SdimREGISTER_CHECKER(MallocPessimistic) 2206234353SdimREGISTER_CHECKER(MallocOptimistic) 2207249423SdimREGISTER_CHECKER(NewDeleteChecker) 2208249423SdimREGISTER_CHECKER(MismatchedDeallocatorChecker) 2209