MallocChecker.cpp revision 30838b994527d12e269abb14d395b1878e78c16d
1//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines malloc/free checker, which checks for potential memory 11// leaks, double free, and use-after-free problems. 12// 13//===----------------------------------------------------------------------===// 14 15#include "ClangSACheckers.h" 16#include "clang/StaticAnalyzer/Core/Checker.h" 17#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 19#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 20#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 21#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 22#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 23#include "clang/Basic/SourceManager.h" 24#include "llvm/ADT/ImmutableMap.h" 25#include "llvm/ADT/SmallString.h" 26#include "llvm/ADT/STLExtras.h" 27using namespace clang; 28using namespace ento; 29 30namespace { 31 32class RefState { 33 enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped, 34 Relinquished } K; 35 const Stmt *S; 36 37public: 38 RefState(Kind k, const Stmt *s) : K(k), S(s) {} 39 40 bool isAllocated() const { return K == AllocateUnchecked; } 41 //bool isFailed() const { return K == AllocateFailed; } 42 bool isReleased() const { return K == Released; } 43 //bool isEscaped() const { return K == Escaped; } 44 //bool isRelinquished() const { return K == Relinquished; } 45 const Stmt *getStmt() const { return S; } 46 47 bool operator==(const RefState &X) const { 48 return K == X.K && S == X.S; 49 } 50 51 static RefState getAllocateUnchecked(const Stmt *s) { 52 return RefState(AllocateUnchecked, s); 53 } 54 static RefState getAllocateFailed() { 55 return RefState(AllocateFailed, 0); 56 } 57 static RefState getReleased(const Stmt *s) { return RefState(Released, s); } 58 static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); } 59 static RefState getRelinquished(const Stmt *s) { 60 return RefState(Relinquished, s); 61 } 62 63 void Profile(llvm::FoldingSetNodeID &ID) const { 64 ID.AddInteger(K); 65 ID.AddPointer(S); 66 } 67}; 68 69class MallocChecker : public Checker<check::DeadSymbols, 70 check::EndPath, 71 check::PreStmt<ReturnStmt>, 72 check::PostStmt<CallExpr>, 73 check::Location, 74 check::Bind, 75 eval::Assume, 76 check::RegionChanges> 77{ 78 mutable OwningPtr<BuiltinBug> BT_DoubleFree; 79 mutable OwningPtr<BuiltinBug> BT_Leak; 80 mutable OwningPtr<BuiltinBug> BT_UseFree; 81 mutable OwningPtr<BuiltinBug> BT_UseRelinquished; 82 mutable OwningPtr<BuiltinBug> BT_BadFree; 83 mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc; 84 85public: 86 MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {} 87 88 /// In pessimistic mode, the checker assumes that it does not know which 89 /// functions might free the memory. 90 struct ChecksFilter { 91 DefaultBool CMallocPessimistic; 92 DefaultBool CMallocOptimistic; 93 }; 94 95 ChecksFilter Filter; 96 97 void initIdentifierInfo(CheckerContext &C) const; 98 99 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; 100 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 101 void checkEndPath(CheckerContext &C) const; 102 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; 103 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, 104 bool Assumption) const; 105 void checkLocation(SVal l, bool isLoad, const Stmt *S, 106 CheckerContext &C) const; 107 void checkBind(SVal location, SVal val, const Stmt*S, 108 CheckerContext &C) const; 109 ProgramStateRef 110 checkRegionChanges(ProgramStateRef state, 111 const StoreManager::InvalidatedSymbols *invalidated, 112 ArrayRef<const MemRegion *> ExplicitRegions, 113 ArrayRef<const MemRegion *> Regions) const; 114 bool wantsRegionChangeUpdate(ProgramStateRef state) const { 115 return true; 116 } 117 118private: 119 static void MallocMem(CheckerContext &C, const CallExpr *CE); 120 static void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, 121 const OwnershipAttr* Att); 122 static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, 123 const Expr *SizeEx, SVal Init, 124 ProgramStateRef state) { 125 return MallocMemAux(C, CE, 126 state->getSVal(SizeEx, C.getLocationContext()), 127 Init, state); 128 } 129 static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE, 130 SVal SizeEx, SVal Init, 131 ProgramStateRef state); 132 133 void FreeMem(CheckerContext &C, const CallExpr *CE) const; 134 void FreeMemAttr(CheckerContext &C, const CallExpr *CE, 135 const OwnershipAttr* Att) const; 136 ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE, 137 ProgramStateRef state, unsigned Num, 138 bool Hold) const; 139 140 void ReallocMem(CheckerContext &C, const CallExpr *CE) const; 141 static void CallocMem(CheckerContext &C, const CallExpr *CE); 142 143 bool checkEscape(SymbolRef Sym, const Stmt *S, CheckerContext &C) const; 144 bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, 145 const Stmt *S = 0) const; 146 147 static bool SummarizeValue(raw_ostream &os, SVal V); 148 static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); 149 void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const; 150 151 void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const; 152 153 /// The bug visitor which allows us to print extra diagnostics along the 154 /// BugReport path. For example, showing the allocation site of the leaked 155 /// region. 156 class MallocBugVisitor : public BugReporterVisitor { 157 protected: 158 // The allocated region symbol tracked by the main analysis. 159 SymbolRef Sym; 160 161 public: 162 MallocBugVisitor(SymbolRef S) : Sym(S) {} 163 virtual ~MallocBugVisitor() {} 164 165 void Profile(llvm::FoldingSetNodeID &ID) const { 166 static int X = 0; 167 ID.AddPointer(&X); 168 ID.AddPointer(Sym); 169 } 170 171 inline bool isAllocated(const RefState *S, const RefState *SPrev) { 172 // Did not track -> allocated. Other state (released) -> allocated. 173 return ((S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated())); 174 } 175 176 inline bool isReleased(const RefState *S, const RefState *SPrev) { 177 // Did not track -> released. Other state (allocated) -> released. 178 return ((S && S->isReleased()) && (!SPrev || !SPrev->isReleased())); 179 } 180 181 PathDiagnosticPiece *VisitNode(const ExplodedNode *N, 182 const ExplodedNode *PrevN, 183 BugReporterContext &BRC, 184 BugReport &BR); 185 }; 186}; 187} // end anonymous namespace 188 189typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy; 190typedef llvm::ImmutableMap<SymbolRef, SymbolRef> SymRefToSymRefTy; 191class RegionState {}; 192class ReallocPairs {}; 193namespace clang { 194namespace ento { 195 template <> 196 struct ProgramStateTrait<RegionState> 197 : public ProgramStatePartialTrait<RegionStateTy> { 198 static void *GDMIndex() { static int x; return &x; } 199 }; 200 201 template <> 202 struct ProgramStateTrait<ReallocPairs> 203 : public ProgramStatePartialTrait<SymRefToSymRefTy> { 204 static void *GDMIndex() { static int x; return &x; } 205 }; 206} 207} 208 209namespace { 210class StopTrackingCallback : public SymbolVisitor { 211 ProgramStateRef state; 212public: 213 StopTrackingCallback(ProgramStateRef st) : state(st) {} 214 ProgramStateRef getState() const { return state; } 215 216 bool VisitSymbol(SymbolRef sym) { 217 state = state->remove<RegionState>(sym); 218 return true; 219 } 220}; 221} // end anonymous namespace 222 223void MallocChecker::initIdentifierInfo(CheckerContext &C) const { 224 ASTContext &Ctx = C.getASTContext(); 225 if (!II_malloc) 226 II_malloc = &Ctx.Idents.get("malloc"); 227 if (!II_free) 228 II_free = &Ctx.Idents.get("free"); 229 if (!II_realloc) 230 II_realloc = &Ctx.Idents.get("realloc"); 231 if (!II_calloc) 232 II_calloc = &Ctx.Idents.get("calloc"); 233} 234 235void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { 236 const FunctionDecl *FD = C.getCalleeDecl(CE); 237 if (!FD) 238 return; 239 initIdentifierInfo(C); 240 241 if (FD->getIdentifier() == II_malloc) { 242 MallocMem(C, CE); 243 return; 244 } 245 if (FD->getIdentifier() == II_realloc) { 246 ReallocMem(C, CE); 247 return; 248 } 249 250 if (FD->getIdentifier() == II_calloc) { 251 CallocMem(C, CE); 252 return; 253 } 254 255 if (FD->getIdentifier() == II_free) { 256 FreeMem(C, CE); 257 return; 258 } 259 260 if (Filter.CMallocOptimistic) 261 // Check all the attributes, if there are any. 262 // There can be multiple of these attributes. 263 if (FD->hasAttrs()) { 264 for (specific_attr_iterator<OwnershipAttr> 265 i = FD->specific_attr_begin<OwnershipAttr>(), 266 e = FD->specific_attr_end<OwnershipAttr>(); 267 i != e; ++i) { 268 switch ((*i)->getOwnKind()) { 269 case OwnershipAttr::Returns: { 270 MallocMemReturnsAttr(C, CE, *i); 271 return; 272 } 273 case OwnershipAttr::Takes: 274 case OwnershipAttr::Holds: { 275 FreeMemAttr(C, CE, *i); 276 return; 277 } 278 } 279 } 280 } 281 282 // Check use after free, when a freed pointer is passed to a call. 283 ProgramStateRef State = C.getState(); 284 for (CallExpr::const_arg_iterator I = CE->arg_begin(), 285 E = CE->arg_end(); I != E; ++I) { 286 const Expr *A = *I; 287 if (A->getType().getTypePtr()->isAnyPointerType()) { 288 SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol(); 289 if (!Sym) 290 continue; 291 if (checkUseAfterFree(Sym, C, A)) 292 return; 293 } 294 } 295 296 // The pointer might escape through a function call. 297 // TODO: This should be rewritten to take into account inlining. 298 if (Filter.CMallocPessimistic) { 299 SourceLocation FLoc = FD->getLocation(); 300 // We assume that the pointers cannot escape through calls to system 301 // functions. 302 if (C.getSourceManager().isInSystemHeader(FLoc)) 303 return; 304 305 ProgramStateRef State = C.getState(); 306 for (CallExpr::const_arg_iterator I = CE->arg_begin(), 307 E = CE->arg_end(); I != E; ++I) { 308 const Expr *A = *I; 309 if (A->getType().getTypePtr()->isAnyPointerType()) { 310 SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol(); 311 if (!Sym) 312 continue; 313 checkEscape(Sym, A, C); 314 } 315 } 316 } 317} 318 319void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) { 320 ProgramStateRef state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), 321 C.getState()); 322 C.addTransition(state); 323} 324 325void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, 326 const OwnershipAttr* Att) { 327 if (Att->getModule() != "malloc") 328 return; 329 330 OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 331 if (I != E) { 332 ProgramStateRef state = 333 MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState()); 334 C.addTransition(state); 335 return; 336 } 337 ProgramStateRef state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), 338 C.getState()); 339 C.addTransition(state); 340} 341 342ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C, 343 const CallExpr *CE, 344 SVal Size, SVal Init, 345 ProgramStateRef state) { 346 SValBuilder &svalBuilder = C.getSValBuilder(); 347 348 // Get the return value. 349 SVal retVal = state->getSVal(CE, C.getLocationContext()); 350 351 // Fill the region with the initialization value. 352 state = state->bindDefault(retVal, Init); 353 354 // Set the region's extent equal to the Size parameter. 355 const SymbolicRegion *R = 356 dyn_cast_or_null<SymbolicRegion>(retVal.getAsRegion()); 357 if (!R || !isa<DefinedOrUnknownSVal>(Size)) 358 return 0; 359 360 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 361 DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size); 362 DefinedOrUnknownSVal extentMatchesSize = 363 svalBuilder.evalEQ(state, Extent, DefinedSize); 364 365 state = state->assume(extentMatchesSize, true); 366 assert(state); 367 368 SymbolRef Sym = retVal.getAsLocSymbol(); 369 assert(Sym); 370 371 // Set the symbol's state to Allocated. 372 return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE)); 373} 374 375void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) const { 376 ProgramStateRef state = FreeMemAux(C, CE, C.getState(), 0, false); 377 378 if (state) 379 C.addTransition(state); 380} 381 382void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE, 383 const OwnershipAttr* Att) const { 384 if (Att->getModule() != "malloc") 385 return; 386 387 for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); 388 I != E; ++I) { 389 ProgramStateRef state = 390 FreeMemAux(C, CE, C.getState(), *I, 391 Att->getOwnKind() == OwnershipAttr::Holds); 392 if (state) 393 C.addTransition(state); 394 } 395} 396 397ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, 398 const CallExpr *CE, 399 ProgramStateRef state, 400 unsigned Num, 401 bool Hold) const { 402 const Expr *ArgExpr = CE->getArg(Num); 403 SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext()); 404 if (!isa<DefinedOrUnknownSVal>(ArgVal)) 405 return 0; 406 DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal); 407 408 // Check for null dereferences. 409 if (!isa<Loc>(location)) 410 return 0; 411 412 // FIXME: Technically using 'Assume' here can result in a path 413 // bifurcation. In such cases we need to return two states, not just one. 414 ProgramStateRef notNullState, nullState; 415 llvm::tie(notNullState, nullState) = state->assume(location); 416 417 // The explicit NULL case, no operation is performed. 418 if (nullState && !notNullState) 419 return 0; 420 421 assert(notNullState); 422 423 // Unknown values could easily be okay 424 // Undefined values are handled elsewhere 425 if (ArgVal.isUnknownOrUndef()) 426 return 0; 427 428 const MemRegion *R = ArgVal.getAsRegion(); 429 430 // Nonlocs can't be freed, of course. 431 // Non-region locations (labels and fixed addresses) also shouldn't be freed. 432 if (!R) { 433 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 434 return 0; 435 } 436 437 R = R->StripCasts(); 438 439 // Blocks might show up as heap data, but should not be free()d 440 if (isa<BlockDataRegion>(R)) { 441 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 442 return 0; 443 } 444 445 const MemSpaceRegion *MS = R->getMemorySpace(); 446 447 // Parameters, locals, statics, and globals shouldn't be freed. 448 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) { 449 // FIXME: at the time this code was written, malloc() regions were 450 // represented by conjured symbols, which are all in UnknownSpaceRegion. 451 // This means that there isn't actually anything from HeapSpaceRegion 452 // that should be freed, even though we allow it here. 453 // Of course, free() can work on memory allocated outside the current 454 // function, so UnknownSpaceRegion is always a possibility. 455 // False negatives are better than false positives. 456 457 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 458 return 0; 459 } 460 461 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R); 462 // Various cases could lead to non-symbol values here. 463 // For now, ignore them. 464 if (!SR) 465 return 0; 466 467 SymbolRef Sym = SR->getSymbol(); 468 const RefState *RS = state->get<RegionState>(Sym); 469 470 // If the symbol has not been tracked, return. This is possible when free() is 471 // called on a pointer that does not get its pointee directly from malloc(). 472 // Full support of this requires inter-procedural analysis. 473 if (!RS) 474 return 0; 475 476 // Check double free. 477 if (RS->isReleased()) { 478 if (ExplodedNode *N = C.generateSink()) { 479 if (!BT_DoubleFree) 480 BT_DoubleFree.reset( 481 new BuiltinBug("Double free", 482 "Try to free a memory block that has been released")); 483 BugReport *R = new BugReport(*BT_DoubleFree, 484 BT_DoubleFree->getDescription(), N); 485 R->addVisitor(new MallocBugVisitor(Sym)); 486 C.EmitReport(R); 487 } 488 return 0; 489 } 490 491 // Normal free. 492 if (Hold) 493 return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE)); 494 return notNullState->set<RegionState>(Sym, RefState::getReleased(CE)); 495} 496 497bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { 498 if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V)) 499 os << "an integer (" << IntVal->getValue() << ")"; 500 else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V)) 501 os << "a constant address (" << ConstAddr->getValue() << ")"; 502 else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V)) 503 os << "the address of the label '" << Label->getLabel()->getName() << "'"; 504 else 505 return false; 506 507 return true; 508} 509 510bool MallocChecker::SummarizeRegion(raw_ostream &os, 511 const MemRegion *MR) { 512 switch (MR->getKind()) { 513 case MemRegion::FunctionTextRegionKind: { 514 const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 515 if (FD) 516 os << "the address of the function '" << *FD << '\''; 517 else 518 os << "the address of a function"; 519 return true; 520 } 521 case MemRegion::BlockTextRegionKind: 522 os << "block text"; 523 return true; 524 case MemRegion::BlockDataRegionKind: 525 // FIXME: where the block came from? 526 os << "a block"; 527 return true; 528 default: { 529 const MemSpaceRegion *MS = MR->getMemorySpace(); 530 531 if (isa<StackLocalsSpaceRegion>(MS)) { 532 const VarRegion *VR = dyn_cast<VarRegion>(MR); 533 const VarDecl *VD; 534 if (VR) 535 VD = VR->getDecl(); 536 else 537 VD = NULL; 538 539 if (VD) 540 os << "the address of the local variable '" << VD->getName() << "'"; 541 else 542 os << "the address of a local stack variable"; 543 return true; 544 } 545 546 if (isa<StackArgumentsSpaceRegion>(MS)) { 547 const VarRegion *VR = dyn_cast<VarRegion>(MR); 548 const VarDecl *VD; 549 if (VR) 550 VD = VR->getDecl(); 551 else 552 VD = NULL; 553 554 if (VD) 555 os << "the address of the parameter '" << VD->getName() << "'"; 556 else 557 os << "the address of a parameter"; 558 return true; 559 } 560 561 if (isa<GlobalsSpaceRegion>(MS)) { 562 const VarRegion *VR = dyn_cast<VarRegion>(MR); 563 const VarDecl *VD; 564 if (VR) 565 VD = VR->getDecl(); 566 else 567 VD = NULL; 568 569 if (VD) { 570 if (VD->isStaticLocal()) 571 os << "the address of the static variable '" << VD->getName() << "'"; 572 else 573 os << "the address of the global variable '" << VD->getName() << "'"; 574 } else 575 os << "the address of a global variable"; 576 return true; 577 } 578 579 return false; 580 } 581 } 582} 583 584void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, 585 SourceRange range) const { 586 if (ExplodedNode *N = C.generateSink()) { 587 if (!BT_BadFree) 588 BT_BadFree.reset(new BuiltinBug("Bad free")); 589 590 SmallString<100> buf; 591 llvm::raw_svector_ostream os(buf); 592 593 const MemRegion *MR = ArgVal.getAsRegion(); 594 if (MR) { 595 while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) 596 MR = ER->getSuperRegion(); 597 598 // Special case for alloca() 599 if (isa<AllocaRegion>(MR)) 600 os << "Argument to free() was allocated by alloca(), not malloc()"; 601 else { 602 os << "Argument to free() is "; 603 if (SummarizeRegion(os, MR)) 604 os << ", which is not memory allocated by malloc()"; 605 else 606 os << "not memory allocated by malloc()"; 607 } 608 } else { 609 os << "Argument to free() is "; 610 if (SummarizeValue(os, ArgVal)) 611 os << ", which is not memory allocated by malloc()"; 612 else 613 os << "not memory allocated by malloc()"; 614 } 615 616 BugReport *R = new BugReport(*BT_BadFree, os.str(), N); 617 R->addRange(range); 618 C.EmitReport(R); 619 } 620} 621 622void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { 623 ProgramStateRef state = C.getState(); 624 const Expr *arg0Expr = CE->getArg(0); 625 const LocationContext *LCtx = C.getLocationContext(); 626 SVal Arg0Val = state->getSVal(arg0Expr, LCtx); 627 if (!isa<DefinedOrUnknownSVal>(Arg0Val)) 628 return; 629 DefinedOrUnknownSVal arg0Val = cast<DefinedOrUnknownSVal>(Arg0Val); 630 631 SValBuilder &svalBuilder = C.getSValBuilder(); 632 633 DefinedOrUnknownSVal PtrEQ = 634 svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull()); 635 636 // Get the size argument. If there is no size arg then give up. 637 const Expr *Arg1 = CE->getArg(1); 638 if (!Arg1) 639 return; 640 641 // Get the value of the size argument. 642 SVal Arg1ValG = state->getSVal(Arg1, LCtx); 643 if (!isa<DefinedOrUnknownSVal>(Arg1ValG)) 644 return; 645 DefinedOrUnknownSVal Arg1Val = cast<DefinedOrUnknownSVal>(Arg1ValG); 646 647 // Compare the size argument to 0. 648 DefinedOrUnknownSVal SizeZero = 649 svalBuilder.evalEQ(state, Arg1Val, 650 svalBuilder.makeIntValWithPtrWidth(0, false)); 651 652 ProgramStateRef StatePtrIsNull, StatePtrNotNull; 653 llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ); 654 ProgramStateRef StateSizeIsZero, StateSizeNotZero; 655 llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero); 656 // We only assume exceptional states if they are definitely true; if the 657 // state is under-constrained, assume regular realloc behavior. 658 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull; 659 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero; 660 661 // If the ptr is NULL and the size is not 0, the call is equivalent to 662 // malloc(size). 663 if ( PrtIsNull && !SizeIsZero) { 664 ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1), 665 UndefinedVal(), StatePtrIsNull); 666 C.addTransition(stateMalloc); 667 return; 668 } 669 670 if (PrtIsNull && SizeIsZero) 671 return; 672 673 // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size). 674 assert(!PrtIsNull); 675 SymbolRef FromPtr = arg0Val.getAsSymbol(); 676 SVal RetVal = state->getSVal(CE, LCtx); 677 SymbolRef ToPtr = RetVal.getAsSymbol(); 678 if (!FromPtr || !ToPtr) 679 return; 680 681 // If the size is 0, free the memory. 682 if (SizeIsZero) 683 if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero,0,false)){ 684 // The semantics of the return value are: 685 // If size was equal to 0, either NULL or a pointer suitable to be passed 686 // to free() is returned. 687 stateFree = stateFree->set<ReallocPairs>(ToPtr, FromPtr); 688 C.addTransition(stateFree); 689 return; 690 } 691 692 // Default behavior. 693 if (ProgramStateRef stateFree = FreeMemAux(C, CE, state, 0, false)) { 694 // FIXME: We should copy the content of the original buffer. 695 ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 696 UnknownVal(), stateFree); 697 if (!stateRealloc) 698 return; 699 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr, FromPtr); 700 C.addTransition(stateRealloc); 701 return; 702 } 703} 704 705void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { 706 ProgramStateRef state = C.getState(); 707 SValBuilder &svalBuilder = C.getSValBuilder(); 708 const LocationContext *LCtx = C.getLocationContext(); 709 SVal count = state->getSVal(CE->getArg(0), LCtx); 710 SVal elementSize = state->getSVal(CE->getArg(1), LCtx); 711 SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize, 712 svalBuilder.getContext().getSizeType()); 713 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); 714 715 C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state)); 716} 717 718void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, 719 CheckerContext &C) const { 720 assert(N); 721 if (!BT_Leak) { 722 BT_Leak.reset(new BuiltinBug("Memory leak", 723 "Allocated memory never released. Potential memory leak.")); 724 // Leaks should not be reported if they are post-dominated by a sink: 725 // (1) Sinks are higher importance bugs. 726 // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending 727 // with __noreturn functions such as assert() or exit(). We choose not 728 // to report leaks on such paths. 729 BT_Leak->setSuppressOnSink(true); 730 } 731 732 BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); 733 R->addVisitor(new MallocBugVisitor(Sym)); 734 C.EmitReport(R); 735} 736 737void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, 738 CheckerContext &C) const 739{ 740 if (!SymReaper.hasDeadSymbols()) 741 return; 742 743 ProgramStateRef state = C.getState(); 744 RegionStateTy RS = state->get<RegionState>(); 745 RegionStateTy::Factory &F = state->get_context<RegionState>(); 746 747 bool generateReport = false; 748 llvm::SmallVector<SymbolRef, 2> Errors; 749 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 750 if (SymReaper.isDead(I->first)) { 751 if (I->second.isAllocated()) { 752 generateReport = true; 753 Errors.push_back(I->first); 754 } 755 // Remove the dead symbol from the map. 756 RS = F.remove(RS, I->first); 757 758 } 759 } 760 761 // Cleanup the Realloc Pairs Map. 762 SymRefToSymRefTy RP = state->get<ReallocPairs>(); 763 for (SymRefToSymRefTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 764 if (SymReaper.isDead(I->first) || SymReaper.isDead(I->second)) { 765 state = state->remove<ReallocPairs>(I->first); 766 } 767 } 768 769 ExplodedNode *N = C.addTransition(state->set<RegionState>(RS)); 770 771 if (N && generateReport) { 772 for (llvm::SmallVector<SymbolRef, 2>::iterator 773 I = Errors.begin(), E = Errors.end(); I != E; ++I) { 774 reportLeak(*I, N, C); 775 } 776 } 777} 778 779void MallocChecker::checkEndPath(CheckerContext &C) const { 780 ProgramStateRef state = C.getState(); 781 RegionStateTy M = state->get<RegionState>(); 782 783 for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { 784 RefState RS = I->second; 785 if (RS.isAllocated()) { 786 ExplodedNode *N = C.addTransition(state); 787 if (N) 788 reportLeak(I->first, N, C); 789 } 790 } 791} 792 793bool MallocChecker::checkEscape(SymbolRef Sym, const Stmt *S, 794 CheckerContext &C) const { 795 ProgramStateRef state = C.getState(); 796 const RefState *RS = state->get<RegionState>(Sym); 797 if (!RS) 798 return false; 799 800 if (RS->isAllocated()) { 801 state = state->set<RegionState>(Sym, RefState::getEscaped(S)); 802 C.addTransition(state); 803 return true; 804 } 805 return false; 806} 807 808void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { 809 const Expr *E = S->getRetValue(); 810 if (!E) 811 return; 812 813 // Check if we are returning a symbol. 814 SymbolRef Sym = C.getState()->getSVal(E, C.getLocationContext()).getAsSymbol(); 815 if (!Sym) 816 return; 817 818 // Check if we are returning freed memory. 819 if (checkUseAfterFree(Sym, C, S)) 820 return; 821 822 // Check if the symbol is escaping. 823 checkEscape(Sym, S, C); 824} 825 826bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, 827 const Stmt *S) const { 828 assert(Sym); 829 const RefState *RS = C.getState()->get<RegionState>(Sym); 830 if (RS && RS->isReleased()) { 831 if (ExplodedNode *N = C.generateSink()) { 832 if (!BT_UseFree) 833 BT_UseFree.reset(new BuiltinBug("Use of dynamically allocated memory " 834 "after it is freed.")); 835 836 BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),N); 837 if (S) 838 R->addRange(S->getSourceRange()); 839 R->addVisitor(new MallocBugVisitor(Sym)); 840 C.EmitReport(R); 841 return true; 842 } 843 } 844 return false; 845} 846 847// Check if the location is a freed symbolic region. 848void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S, 849 CheckerContext &C) const { 850 SymbolRef Sym = l.getLocSymbolInBase(); 851 if (Sym) 852 checkUseAfterFree(Sym, C); 853} 854 855//===----------------------------------------------------------------------===// 856// Check various ways a symbol can be invalidated. 857// TODO: This logic (the next 3 functions) is copied/similar to the 858// RetainRelease checker. We might want to factor this out. 859//===----------------------------------------------------------------------===// 860 861// Stop tracking symbols when a value escapes as a result of checkBind. 862// A value escapes in three possible cases: 863// (1) we are binding to something that is not a memory region. 864// (2) we are binding to a memregion that does not have stack storage 865// (3) we are binding to a memregion with stack storage that the store 866// does not understand. 867void MallocChecker::checkBind(SVal loc, SVal val, const Stmt *S, 868 CheckerContext &C) const { 869 // Are we storing to something that causes the value to "escape"? 870 bool escapes = true; 871 ProgramStateRef state = C.getState(); 872 873 if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) { 874 escapes = !regionLoc->getRegion()->hasStackStorage(); 875 876 if (!escapes) { 877 // To test (3), generate a new state with the binding added. If it is 878 // the same state, then it escapes (since the store cannot represent 879 // the binding). 880 escapes = (state == (state->bindLoc(*regionLoc, val))); 881 } 882 } 883 884 // If our store can represent the binding and we aren't storing to something 885 // that doesn't have local storage then just return and have the simulation 886 // state continue as is. 887 if (!escapes) 888 return; 889 890 // Otherwise, find all symbols referenced by 'val' that we are tracking 891 // and stop tracking them. 892 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState(); 893 C.addTransition(state); 894} 895 896// If a symbolic region is assumed to NULL (or another constant), stop tracking 897// it - assuming that allocation failed on this path. 898ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state, 899 SVal Cond, 900 bool Assumption) const { 901 RegionStateTy RS = state->get<RegionState>(); 902 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 903 // If the symbol is assumed to NULL or another constant, this will 904 // return an APSInt*. 905 if (state->getSymVal(I.getKey())) 906 state = state->remove<RegionState>(I.getKey()); 907 } 908 909 // Realloc returns 0 when reallocation fails, which means that we should 910 // restore the state of the pointer being reallocated. 911 SymRefToSymRefTy RP = state->get<ReallocPairs>(); 912 for (SymRefToSymRefTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 913 // If the symbol is assumed to NULL or another constant, this will 914 // return an APSInt*. 915 if (state->getSymVal(I.getKey())) { 916 const RefState *RS = state->get<RegionState>(I.getData()); 917 if (RS) { 918 if (RS->isReleased()) 919 state = state->set<RegionState>(I.getData(), 920 RefState::getAllocateUnchecked(RS->getStmt())); 921 if (RS->isAllocated()) 922 state = state->set<RegionState>(I.getData(), 923 RefState::getReleased(RS->getStmt())); 924 } 925 state = state->remove<ReallocPairs>(I.getKey()); 926 } 927 } 928 929 return state; 930} 931 932// If the symbol we are tracking is invalidated, but not explicitly (ex: the &p 933// escapes, when we are tracking p), do not track the symbol as we cannot reason 934// about it anymore. 935ProgramStateRef 936MallocChecker::checkRegionChanges(ProgramStateRef state, 937 const StoreManager::InvalidatedSymbols *invalidated, 938 ArrayRef<const MemRegion *> ExplicitRegions, 939 ArrayRef<const MemRegion *> Regions) const { 940 if (!invalidated) 941 return state; 942 943 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols; 944 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(), 945 E = ExplicitRegions.end(); I != E; ++I) { 946 if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>()) 947 WhitelistedSymbols.insert(SR->getSymbol()); 948 } 949 950 for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(), 951 E = invalidated->end(); I!=E; ++I) { 952 SymbolRef sym = *I; 953 if (WhitelistedSymbols.count(sym)) 954 continue; 955 // Don't track the symbol. 956 state = state->remove<RegionState>(sym); 957 } 958 return state; 959} 960 961PathDiagnosticPiece * 962MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, 963 const ExplodedNode *PrevN, 964 BugReporterContext &BRC, 965 BugReport &BR) { 966 const RefState *RS = N->getState()->get<RegionState>(Sym); 967 const RefState *RSPrev = PrevN->getState()->get<RegionState>(Sym); 968 if (!RS && !RSPrev) 969 return 0; 970 971 // We expect the interesting locations be StmtPoints corresponding to call 972 // expressions. We do not support indirect function calls as of now. 973 const CallExpr *CE = 0; 974 if (isa<StmtPoint>(N->getLocation())) 975 CE = dyn_cast<CallExpr>(cast<StmtPoint>(N->getLocation()).getStmt()); 976 if (!CE) 977 return 0; 978 const FunctionDecl *funDecl = CE->getDirectCallee(); 979 if (!funDecl) 980 return 0; 981 982 // Find out if this is an interesting point and what is the kind. 983 const char *Msg = 0; 984 if (isAllocated(RS, RSPrev)) 985 Msg = "Memory is allocated here"; 986 else if (isReleased(RS, RSPrev)) 987 Msg = "Memory is released here"; 988 if (!Msg) 989 return 0; 990 991 // Generate the extra diagnostic. 992 PathDiagnosticLocation Pos(CE, BRC.getSourceManager(), 993 N->getLocationContext()); 994 return new PathDiagnosticEventPiece(Pos, Msg); 995} 996 997 998#define REGISTER_CHECKER(name) \ 999void ento::register##name(CheckerManager &mgr) {\ 1000 mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\ 1001} 1002 1003REGISTER_CHECKER(MallocPessimistic) 1004REGISTER_CHECKER(MallocOptimistic) 1005