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