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" 27 using namespace clang; 28 using namespace ento; 29 30 namespace { 31 32 class RefState { 33 enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped, 34 Relinquished } K; 35 const Stmt *S; 36 37 public: 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 69 class 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 85 public: 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 118 private: 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 189 typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy; 190 typedef llvm::ImmutableMap<SymbolRef, SymbolRef> SymRefToSymRefTy; 191 class RegionState {}; 192 class ReallocPairs {}; 193 namespace clang { 194 namespace 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 209 namespace { 210 class StopTrackingCallback : public SymbolVisitor { 211 ProgramStateRef state; 212 public: 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 223 void 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 235 void 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 319 void 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 325 void 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 342 ProgramStateRef 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 375 void 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 382 void 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 397 ProgramStateRef 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 // The explicit NULL case, no operation is performed. 413 ProgramStateRef notNullState, nullState; 414 llvm::tie(notNullState, nullState) = state->assume(location); 415 if (nullState && !notNullState) 416 return 0; 417 418 // Unknown values could easily be okay 419 // Undefined values are handled elsewhere 420 if (ArgVal.isUnknownOrUndef()) 421 return 0; 422 423 const MemRegion *R = ArgVal.getAsRegion(); 424 425 // Nonlocs can't be freed, of course. 426 // Non-region locations (labels and fixed addresses) also shouldn't be freed. 427 if (!R) { 428 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 429 return 0; 430 } 431 432 R = R->StripCasts(); 433 434 // Blocks might show up as heap data, but should not be free()d 435 if (isa<BlockDataRegion>(R)) { 436 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 437 return 0; 438 } 439 440 const MemSpaceRegion *MS = R->getMemorySpace(); 441 442 // Parameters, locals, statics, and globals shouldn't be freed. 443 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) { 444 // FIXME: at the time this code was written, malloc() regions were 445 // represented by conjured symbols, which are all in UnknownSpaceRegion. 446 // This means that there isn't actually anything from HeapSpaceRegion 447 // that should be freed, even though we allow it here. 448 // Of course, free() can work on memory allocated outside the current 449 // function, so UnknownSpaceRegion is always a possibility. 450 // False negatives are better than false positives. 451 452 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange()); 453 return 0; 454 } 455 456 const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R); 457 // Various cases could lead to non-symbol values here. 458 // For now, ignore them. 459 if (!SR) 460 return 0; 461 462 SymbolRef Sym = SR->getSymbol(); 463 const RefState *RS = state->get<RegionState>(Sym); 464 465 // If the symbol has not been tracked, return. This is possible when free() is 466 // called on a pointer that does not get its pointee directly from malloc(). 467 // Full support of this requires inter-procedural analysis. 468 if (!RS) 469 return 0; 470 471 // Check double free. 472 if (RS->isReleased()) { 473 if (ExplodedNode *N = C.generateSink()) { 474 if (!BT_DoubleFree) 475 BT_DoubleFree.reset( 476 new BuiltinBug("Double free", 477 "Try to free a memory block that has been released")); 478 BugReport *R = new BugReport(*BT_DoubleFree, 479 BT_DoubleFree->getDescription(), N); 480 R->addVisitor(new MallocBugVisitor(Sym)); 481 C.EmitReport(R); 482 } 483 return 0; 484 } 485 486 // Normal free. 487 if (Hold) 488 return state->set<RegionState>(Sym, RefState::getRelinquished(CE)); 489 return state->set<RegionState>(Sym, RefState::getReleased(CE)); 490 } 491 492 bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) { 493 if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V)) 494 os << "an integer (" << IntVal->getValue() << ")"; 495 else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V)) 496 os << "a constant address (" << ConstAddr->getValue() << ")"; 497 else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V)) 498 os << "the address of the label '" << Label->getLabel()->getName() << "'"; 499 else 500 return false; 501 502 return true; 503 } 504 505 bool MallocChecker::SummarizeRegion(raw_ostream &os, 506 const MemRegion *MR) { 507 switch (MR->getKind()) { 508 case MemRegion::FunctionTextRegionKind: { 509 const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 510 if (FD) 511 os << "the address of the function '" << *FD << '\''; 512 else 513 os << "the address of a function"; 514 return true; 515 } 516 case MemRegion::BlockTextRegionKind: 517 os << "block text"; 518 return true; 519 case MemRegion::BlockDataRegionKind: 520 // FIXME: where the block came from? 521 os << "a block"; 522 return true; 523 default: { 524 const MemSpaceRegion *MS = MR->getMemorySpace(); 525 526 if (isa<StackLocalsSpaceRegion>(MS)) { 527 const VarRegion *VR = dyn_cast<VarRegion>(MR); 528 const VarDecl *VD; 529 if (VR) 530 VD = VR->getDecl(); 531 else 532 VD = NULL; 533 534 if (VD) 535 os << "the address of the local variable '" << VD->getName() << "'"; 536 else 537 os << "the address of a local stack variable"; 538 return true; 539 } 540 541 if (isa<StackArgumentsSpaceRegion>(MS)) { 542 const VarRegion *VR = dyn_cast<VarRegion>(MR); 543 const VarDecl *VD; 544 if (VR) 545 VD = VR->getDecl(); 546 else 547 VD = NULL; 548 549 if (VD) 550 os << "the address of the parameter '" << VD->getName() << "'"; 551 else 552 os << "the address of a parameter"; 553 return true; 554 } 555 556 if (isa<GlobalsSpaceRegion>(MS)) { 557 const VarRegion *VR = dyn_cast<VarRegion>(MR); 558 const VarDecl *VD; 559 if (VR) 560 VD = VR->getDecl(); 561 else 562 VD = NULL; 563 564 if (VD) { 565 if (VD->isStaticLocal()) 566 os << "the address of the static variable '" << VD->getName() << "'"; 567 else 568 os << "the address of the global variable '" << VD->getName() << "'"; 569 } else 570 os << "the address of a global variable"; 571 return true; 572 } 573 574 return false; 575 } 576 } 577 } 578 579 void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, 580 SourceRange range) const { 581 if (ExplodedNode *N = C.generateSink()) { 582 if (!BT_BadFree) 583 BT_BadFree.reset(new BuiltinBug("Bad free")); 584 585 SmallString<100> buf; 586 llvm::raw_svector_ostream os(buf); 587 588 const MemRegion *MR = ArgVal.getAsRegion(); 589 if (MR) { 590 while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) 591 MR = ER->getSuperRegion(); 592 593 // Special case for alloca() 594 if (isa<AllocaRegion>(MR)) 595 os << "Argument to free() was allocated by alloca(), not malloc()"; 596 else { 597 os << "Argument to free() is "; 598 if (SummarizeRegion(os, MR)) 599 os << ", which is not memory allocated by malloc()"; 600 else 601 os << "not memory allocated by malloc()"; 602 } 603 } else { 604 os << "Argument to free() is "; 605 if (SummarizeValue(os, ArgVal)) 606 os << ", which is not memory allocated by malloc()"; 607 else 608 os << "not memory allocated by malloc()"; 609 } 610 611 BugReport *R = new BugReport(*BT_BadFree, os.str(), N); 612 R->addRange(range); 613 C.EmitReport(R); 614 } 615 } 616 617 void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { 618 ProgramStateRef state = C.getState(); 619 const Expr *arg0Expr = CE->getArg(0); 620 const LocationContext *LCtx = C.getLocationContext(); 621 SVal Arg0Val = state->getSVal(arg0Expr, LCtx); 622 if (!isa<DefinedOrUnknownSVal>(Arg0Val)) 623 return; 624 DefinedOrUnknownSVal arg0Val = cast<DefinedOrUnknownSVal>(Arg0Val); 625 626 SValBuilder &svalBuilder = C.getSValBuilder(); 627 628 DefinedOrUnknownSVal PtrEQ = 629 svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull()); 630 631 // Get the size argument. If there is no size arg then give up. 632 const Expr *Arg1 = CE->getArg(1); 633 if (!Arg1) 634 return; 635 636 // Get the value of the size argument. 637 SVal Arg1ValG = state->getSVal(Arg1, LCtx); 638 if (!isa<DefinedOrUnknownSVal>(Arg1ValG)) 639 return; 640 DefinedOrUnknownSVal Arg1Val = cast<DefinedOrUnknownSVal>(Arg1ValG); 641 642 // Compare the size argument to 0. 643 DefinedOrUnknownSVal SizeZero = 644 svalBuilder.evalEQ(state, Arg1Val, 645 svalBuilder.makeIntValWithPtrWidth(0, false)); 646 647 ProgramStateRef StatePtrIsNull, StatePtrNotNull; 648 llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ); 649 ProgramStateRef StateSizeIsZero, StateSizeNotZero; 650 llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero); 651 // We only assume exceptional states if they are definitely true; if the 652 // state is under-constrained, assume regular realloc behavior. 653 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull; 654 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero; 655 656 // If the ptr is NULL and the size is not 0, the call is equivalent to 657 // malloc(size). 658 if ( PrtIsNull && !SizeIsZero) { 659 ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1), 660 UndefinedVal(), StatePtrIsNull); 661 C.addTransition(stateMalloc); 662 return; 663 } 664 665 if (PrtIsNull && SizeIsZero) 666 return; 667 668 // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size). 669 assert(!PrtIsNull); 670 SymbolRef FromPtr = arg0Val.getAsSymbol(); 671 SVal RetVal = state->getSVal(CE, LCtx); 672 SymbolRef ToPtr = RetVal.getAsSymbol(); 673 if (!FromPtr || !ToPtr) 674 return; 675 676 // If the size is 0, free the memory. 677 if (SizeIsZero) 678 if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero,0,false)){ 679 // The semantics of the return value are: 680 // If size was equal to 0, either NULL or a pointer suitable to be passed 681 // to free() is returned. 682 stateFree = stateFree->set<ReallocPairs>(ToPtr, FromPtr); 683 C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr); 684 C.addTransition(stateFree); 685 return; 686 } 687 688 // Default behavior. 689 if (ProgramStateRef stateFree = FreeMemAux(C, CE, state, 0, false)) { 690 // FIXME: We should copy the content of the original buffer. 691 ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 692 UnknownVal(), stateFree); 693 if (!stateRealloc) 694 return; 695 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr, FromPtr); 696 C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr); 697 C.addTransition(stateRealloc); 698 return; 699 } 700 } 701 702 void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { 703 ProgramStateRef state = C.getState(); 704 SValBuilder &svalBuilder = C.getSValBuilder(); 705 const LocationContext *LCtx = C.getLocationContext(); 706 SVal count = state->getSVal(CE->getArg(0), LCtx); 707 SVal elementSize = state->getSVal(CE->getArg(1), LCtx); 708 SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize, 709 svalBuilder.getContext().getSizeType()); 710 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); 711 712 C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state)); 713 } 714 715 void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, 716 CheckerContext &C) const { 717 assert(N); 718 if (!BT_Leak) { 719 BT_Leak.reset(new BuiltinBug("Memory leak", 720 "Allocated memory never released. Potential memory leak.")); 721 // Leaks should not be reported if they are post-dominated by a sink: 722 // (1) Sinks are higher importance bugs. 723 // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending 724 // with __noreturn functions such as assert() or exit(). We choose not 725 // to report leaks on such paths. 726 BT_Leak->setSuppressOnSink(true); 727 } 728 729 BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N); 730 R->addVisitor(new MallocBugVisitor(Sym)); 731 C.EmitReport(R); 732 } 733 734 void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, 735 CheckerContext &C) const 736 { 737 if (!SymReaper.hasDeadSymbols()) 738 return; 739 740 ProgramStateRef state = C.getState(); 741 RegionStateTy RS = state->get<RegionState>(); 742 RegionStateTy::Factory &F = state->get_context<RegionState>(); 743 744 bool generateReport = false; 745 llvm::SmallVector<SymbolRef, 2> Errors; 746 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 747 if (SymReaper.isDead(I->first)) { 748 if (I->second.isAllocated()) { 749 generateReport = true; 750 Errors.push_back(I->first); 751 } 752 // Remove the dead symbol from the map. 753 RS = F.remove(RS, I->first); 754 755 } 756 } 757 758 // Cleanup the Realloc Pairs Map. 759 SymRefToSymRefTy RP = state->get<ReallocPairs>(); 760 for (SymRefToSymRefTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 761 if (SymReaper.isDead(I->first) || SymReaper.isDead(I->second)) { 762 state = state->remove<ReallocPairs>(I->first); 763 } 764 } 765 766 ExplodedNode *N = C.addTransition(state->set<RegionState>(RS)); 767 768 if (N && generateReport) { 769 for (llvm::SmallVector<SymbolRef, 2>::iterator 770 I = Errors.begin(), E = Errors.end(); I != E; ++I) { 771 reportLeak(*I, N, C); 772 } 773 } 774 } 775 776 void MallocChecker::checkEndPath(CheckerContext &C) const { 777 ProgramStateRef state = C.getState(); 778 RegionStateTy M = state->get<RegionState>(); 779 780 for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { 781 RefState RS = I->second; 782 if (RS.isAllocated()) { 783 ExplodedNode *N = C.addTransition(state); 784 if (N) 785 reportLeak(I->first, N, C); 786 } 787 } 788 } 789 790 bool MallocChecker::checkEscape(SymbolRef Sym, const Stmt *S, 791 CheckerContext &C) const { 792 ProgramStateRef state = C.getState(); 793 const RefState *RS = state->get<RegionState>(Sym); 794 if (!RS) 795 return false; 796 797 if (RS->isAllocated()) { 798 state = state->set<RegionState>(Sym, RefState::getEscaped(S)); 799 C.addTransition(state); 800 return true; 801 } 802 return false; 803 } 804 805 void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { 806 const Expr *E = S->getRetValue(); 807 if (!E) 808 return; 809 810 // Check if we are returning a symbol. 811 SymbolRef Sym = C.getState()->getSVal(E, C.getLocationContext()).getAsSymbol(); 812 if (!Sym) 813 return; 814 815 // Check if we are returning freed memory. 816 if (checkUseAfterFree(Sym, C, S)) 817 return; 818 819 // Check if the symbol is escaping. 820 checkEscape(Sym, S, C); 821 } 822 823 bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, 824 const Stmt *S) const { 825 assert(Sym); 826 const RefState *RS = C.getState()->get<RegionState>(Sym); 827 if (RS && RS->isReleased()) { 828 if (ExplodedNode *N = C.generateSink()) { 829 if (!BT_UseFree) 830 BT_UseFree.reset(new BuiltinBug("Use of dynamically allocated memory " 831 "after it is freed.")); 832 833 BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),N); 834 if (S) 835 R->addRange(S->getSourceRange()); 836 R->addVisitor(new MallocBugVisitor(Sym)); 837 C.EmitReport(R); 838 return true; 839 } 840 } 841 return false; 842 } 843 844 // Check if the location is a freed symbolic region. 845 void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S, 846 CheckerContext &C) const { 847 SymbolRef Sym = l.getLocSymbolInBase(); 848 if (Sym) 849 checkUseAfterFree(Sym, C); 850 } 851 852 //===----------------------------------------------------------------------===// 853 // Check various ways a symbol can be invalidated. 854 // TODO: This logic (the next 3 functions) is copied/similar to the 855 // RetainRelease checker. We might want to factor this out. 856 //===----------------------------------------------------------------------===// 857 858 // Stop tracking symbols when a value escapes as a result of checkBind. 859 // A value escapes in three possible cases: 860 // (1) we are binding to something that is not a memory region. 861 // (2) we are binding to a memregion that does not have stack storage 862 // (3) we are binding to a memregion with stack storage that the store 863 // does not understand. 864 void MallocChecker::checkBind(SVal loc, SVal val, const Stmt *S, 865 CheckerContext &C) const { 866 // Are we storing to something that causes the value to "escape"? 867 bool escapes = true; 868 ProgramStateRef state = C.getState(); 869 870 if (loc::MemRegionVal *regionLoc = dyn_cast<loc::MemRegionVal>(&loc)) { 871 escapes = !regionLoc->getRegion()->hasStackStorage(); 872 873 if (!escapes) { 874 // To test (3), generate a new state with the binding added. If it is 875 // the same state, then it escapes (since the store cannot represent 876 // the binding). 877 escapes = (state == (state->bindLoc(*regionLoc, val))); 878 } 879 } 880 881 // If our store can represent the binding and we aren't storing to something 882 // that doesn't have local storage then just return and have the simulation 883 // state continue as is. 884 if (!escapes) 885 return; 886 887 // Otherwise, find all symbols referenced by 'val' that we are tracking 888 // and stop tracking them. 889 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState(); 890 C.addTransition(state); 891 } 892 893 // If a symbolic region is assumed to NULL (or another constant), stop tracking 894 // it - assuming that allocation failed on this path. 895 ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state, 896 SVal Cond, 897 bool Assumption) const { 898 RegionStateTy RS = state->get<RegionState>(); 899 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) { 900 // If the symbol is assumed to NULL or another constant, this will 901 // return an APSInt*. 902 if (state->getSymVal(I.getKey())) 903 state = state->remove<RegionState>(I.getKey()); 904 } 905 906 // Realloc returns 0 when reallocation fails, which means that we should 907 // restore the state of the pointer being reallocated. 908 SymRefToSymRefTy RP = state->get<ReallocPairs>(); 909 for (SymRefToSymRefTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { 910 // If the symbol is assumed to NULL or another constant, this will 911 // return an APSInt*. 912 if (state->getSymVal(I.getKey())) { 913 const RefState *RS = state->get<RegionState>(I.getData()); 914 if (RS) { 915 if (RS->isReleased()) 916 state = state->set<RegionState>(I.getData(), 917 RefState::getAllocateUnchecked(RS->getStmt())); 918 else if (RS->isAllocated()) 919 state = state->set<RegionState>(I.getData(), 920 RefState::getReleased(RS->getStmt())); 921 } 922 state = state->remove<ReallocPairs>(I.getKey()); 923 } 924 } 925 926 return state; 927 } 928 929 // If the symbol we are tracking is invalidated, but not explicitly (ex: the &p 930 // escapes, when we are tracking p), do not track the symbol as we cannot reason 931 // about it anymore. 932 ProgramStateRef 933 MallocChecker::checkRegionChanges(ProgramStateRef state, 934 const StoreManager::InvalidatedSymbols *invalidated, 935 ArrayRef<const MemRegion *> ExplicitRegions, 936 ArrayRef<const MemRegion *> Regions) const { 937 if (!invalidated) 938 return state; 939 940 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols; 941 for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(), 942 E = ExplicitRegions.end(); I != E; ++I) { 943 if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>()) 944 WhitelistedSymbols.insert(SR->getSymbol()); 945 } 946 947 for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(), 948 E = invalidated->end(); I!=E; ++I) { 949 SymbolRef sym = *I; 950 if (WhitelistedSymbols.count(sym)) 951 continue; 952 // Don't track the symbol. 953 state = state->remove<RegionState>(sym); 954 } 955 return state; 956 } 957 958 PathDiagnosticPiece * 959 MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, 960 const ExplodedNode *PrevN, 961 BugReporterContext &BRC, 962 BugReport &BR) { 963 const RefState *RS = N->getState()->get<RegionState>(Sym); 964 const RefState *RSPrev = PrevN->getState()->get<RegionState>(Sym); 965 if (!RS && !RSPrev) 966 return 0; 967 968 // We expect the interesting locations be StmtPoints corresponding to call 969 // expressions. We do not support indirect function calls as of now. 970 const CallExpr *CE = 0; 971 if (isa<StmtPoint>(N->getLocation())) 972 CE = dyn_cast<CallExpr>(cast<StmtPoint>(N->getLocation()).getStmt()); 973 if (!CE) 974 return 0; 975 const FunctionDecl *funDecl = CE->getDirectCallee(); 976 if (!funDecl) 977 return 0; 978 979 // Find out if this is an interesting point and what is the kind. 980 const char *Msg = 0; 981 if (isAllocated(RS, RSPrev)) 982 Msg = "Memory is allocated here"; 983 else if (isReleased(RS, RSPrev)) 984 Msg = "Memory is released here"; 985 if (!Msg) 986 return 0; 987 988 // Generate the extra diagnostic. 989 PathDiagnosticLocation Pos(CE, BRC.getSourceManager(), 990 N->getLocationContext()); 991 return new PathDiagnosticEventPiece(Pos, Msg); 992 } 993 994 995 #define REGISTER_CHECKER(name) \ 996 void ento::register##name(CheckerManager &mgr) {\ 997 mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\ 998 } 999 1000 REGISTER_CHECKER(MallocPessimistic) 1001 REGISTER_CHECKER(MallocOptimistic) 1002