29 #include "llvm/ADT/ImmutableMap.h"
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/SmallString.h"
32 #include "llvm/ADT/StringExtras.h"
36 using namespace clang;
72 RefState(
Kind k,
const Stmt *s,
unsigned family)
73 :
S(s), K(k), Family(family) {
74 assert(family != AF_None);
77 bool isAllocated()
const {
return K == Allocated; }
78 bool isAllocatedOfSizeZero()
const {
return K == AllocatedOfSizeZero; }
79 bool isReleased()
const {
return K == Released; }
80 bool isRelinquished()
const {
return K == Relinquished; }
81 bool isEscaped()
const {
return K == Escaped; }
85 const Stmt *getStmt()
const {
return S; }
88 return K == X.K &&
S == X.S && Family == X.Family;
91 static RefState getAllocated(
unsigned family,
const Stmt *s) {
92 return RefState(Allocated, s, family);
94 static RefState getAllocatedOfSizeZero(
const RefState *RS) {
95 return RefState(AllocatedOfSizeZero, RS->getStmt(),
96 RS->getAllocationFamily());
98 static RefState getReleased(
unsigned family,
const Stmt *s) {
99 return RefState(Released, s, family);
101 static RefState getRelinquished(
unsigned family,
const Stmt *s) {
102 return RefState(Relinquished, s, family);
104 static RefState getEscaped(
const RefState *RS) {
105 return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
108 void Profile(llvm::FoldingSetNodeID &
ID)
const {
111 ID.AddInteger(Family);
114 void dump(raw_ostream &OS)
const {
115 switch (static_cast<Kind>(K)) {
116 #define CASE(ID) case ID: OS << #ID; break;
118 CASE(AllocatedOfSizeZero)
125 LLVM_DUMP_METHOD
void dump()
const {
dump(llvm::errs()); }
129 RPToBeFreedAfterFailure,
133 RPDoNotTrackAfterFailure
145 ReallocatedSym(S),
Kind(K) {}
146 void Profile(llvm::FoldingSetNodeID &ID)
const {
148 ID.AddPointer(ReallocatedSym);
151 return ReallocatedSym == X.ReallocatedSym &&
156 typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo;
158 class MallocChecker :
public Checker<check::DeadSymbols,
159 check::PointerEscape,
160 check::ConstPointerEscape,
161 check::PreStmt<ReturnStmt>,
163 check::PostStmt<CallExpr>,
164 check::PostStmt<CXXNewExpr>,
165 check::PreStmt<CXXDeleteExpr>,
166 check::PostStmt<BlockExpr>,
167 check::PostObjCMessage,
173 : II_alloca(nullptr), II_win_alloca(nullptr), II_malloc(nullptr),
174 II_free(nullptr), II_realloc(nullptr), II_calloc(nullptr),
175 II_valloc(nullptr), II_reallocf(nullptr), II_strndup(nullptr),
176 II_strdup(nullptr), II_win_strdup(nullptr), II_kmalloc(nullptr),
177 II_if_nameindex(nullptr), II_if_freenameindex(nullptr),
178 II_wcsdup(nullptr), II_win_wcsdup(nullptr) {}
185 CK_NewDeleteLeaksChecker,
186 CK_MismatchedDeallocatorChecker,
190 enum class MemoryOperationKind {
210 bool Assumption)
const;
211 void checkLocation(
SVal l,
bool isLoad,
const Stmt *
S,
224 const char *NL,
const char *Sep)
const override;
227 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
228 mutable std::unique_ptr<BugType> BT_DoubleDelete;
229 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
230 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
231 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
232 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
233 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
234 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
235 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
236 mutable IdentifierInfo *II_alloca, *II_win_alloca, *II_malloc, *II_free,
237 *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
238 *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
239 *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
241 mutable Optional<uint64_t> KernelZeroFlagVal;
252 const Expr *
E)
const;
257 const Expr *DeallocExpr)
const;
260 void printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family)
const;
269 MemoryOperationKind MemKind)
const;
275 const unsigned AllocationSizeArg,
280 const OwnershipAttr* Att,
303 const OwnershipAttr* Att,
308 bool &ReleasedAllocated,
309 bool ReturnsNullOnFailure =
false)
const;
311 const Expr *ParentExpr,
314 bool &ReleasedAllocated,
315 bool ReturnsNullOnFailure =
false)
const;
318 bool FreesMemOnFailure,
329 const Stmt *
S)
const;
343 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
const CallEvent *Call,
352 bool(*CheckRefState)(
const RefState*))
const;
359 bool IsALeakCheck =
false)
const;
361 const Stmt *AllocDeallocStmt,
362 bool IsALeakCheck =
false)
const;
364 bool IsALeakCheck =
false)
const;
366 static bool SummarizeValue(raw_ostream &os,
SVal V);
367 static bool SummarizeRegion(raw_ostream &os,
const MemRegion *MR);
369 const Expr *DeallocExpr)
const;
373 const Expr *DeallocExpr,
const RefState *RS,
374 SymbolRef Sym,
bool OwnershipTransferred)
const;
376 const Expr *DeallocExpr,
377 const Expr *AllocExpr =
nullptr)
const;
398 class MallocBugVisitor final
401 enum NotificationMode {
410 NotificationMode Mode;
418 MallocBugVisitor(
SymbolRef S,
bool isLeak =
false)
419 : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
421 void Profile(llvm::FoldingSetNodeID &ID)
const override {
427 inline bool isAllocated(
const RefState *
S,
const RefState *SPrev,
430 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
431 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
432 (!SPrev || !(SPrev->isAllocated() ||
433 SPrev->isAllocatedOfSizeZero())));
436 inline bool isReleased(
const RefState *S,
const RefState *SPrev,
439 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) &&
440 (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
443 inline bool isRelinquished(
const RefState *S,
const RefState *SPrev,
446 return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
447 isa<ObjCPropertyRefExpr>(Stmt)) &&
448 (S && S->isRelinquished()) &&
449 (!SPrev || !SPrev->isRelinquished()));
452 inline bool isReallocFailedCheck(
const RefState *S,
const RefState *SPrev,
458 return ((!Stmt || !isa<CallExpr>(Stmt)) &&
459 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
460 (SPrev && !(SPrev->isAllocated() ||
461 SPrev->isAllocatedOfSizeZero())));
469 std::unique_ptr<PathDiagnosticPiece>
479 return llvm::make_unique<PathDiagnosticEventPiece>(L, BR.
getDescription(),
484 class StackHintGeneratorForReallocationFailed
487 StackHintGeneratorForReallocationFailed(
SymbolRef S, StringRef M)
490 std::string getMessageForArg(
const Expr *ArgE,
491 unsigned ArgIndex)
override {
496 llvm::raw_svector_ostream os(buf);
498 os <<
"Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
499 <<
" parameter failed";
505 return "Reallocation of returned value failed";
527 bool VisitSymbol(SymbolRef sym)
override {
534 void MallocChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
541 II_reallocf = &Ctx.
Idents.
get(
"reallocf");
548 II_if_nameindex = &Ctx.
Idents.
get(
"if_nameindex");
549 II_if_freenameindex = &Ctx.
Idents.
get(
"if_freenameindex");
552 II_win_strdup = &Ctx.
Idents.
get(
"_strdup");
553 II_win_wcsdup = &Ctx.
Idents.
get(
"_wcsdup");
554 II_win_alloca = &Ctx.
Idents.
get(
"_alloca");
558 if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any))
561 if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
564 if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
567 if (isStandardNewDelete(FD, C))
573 bool MallocChecker::isCMemFunction(
const FunctionDecl *FD,
576 MemoryOperationKind MemKind)
const {
580 bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any ||
581 MemKind == MemoryOperationKind::MOK_Free);
582 bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any ||
583 MemKind == MemoryOperationKind::MOK_Allocate);
585 if (FD->getKind() == Decl::Function) {
587 initIdentifierInfo(C);
589 if (Family == AF_Malloc && CheckFree) {
590 if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
594 if (Family == AF_Malloc && CheckAlloc) {
595 if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
596 FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
597 FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
598 FunI == II_win_wcsdup || FunI == II_kmalloc)
602 if (Family == AF_IfNameIndex && CheckFree) {
603 if (FunI == II_if_freenameindex)
607 if (Family == AF_IfNameIndex && CheckAlloc) {
608 if (FunI == II_if_nameindex)
612 if (Family == AF_Alloca && CheckAlloc) {
613 if (FunI == II_alloca || FunI == II_win_alloca)
618 if (Family != AF_Malloc)
621 if (IsOptimistic && FD->hasAttrs()) {
622 for (
const auto *
I : FD->specific_attrs<OwnershipAttr>()) {
623 OwnershipAttr::OwnershipKind OwnKind =
I->getOwnKind();
624 if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
627 }
else if (OwnKind == OwnershipAttr::Returns) {
641 bool MallocChecker::isStandardNewDelete(
const FunctionDecl *FD,
647 if (Kind != OO_New && Kind != OO_Array_New &&
648 Kind != OO_Delete && Kind != OO_Array_Delete)
652 if (isa<CXXMethodDecl>(FD))
659 return II->getName().equals(
"nothrow_t");
691 if (!KernelZeroFlagVal.hasValue()) {
692 if (OS == llvm::Triple::FreeBSD)
693 KernelZeroFlagVal = 0x0100;
694 else if (OS == llvm::Triple::NetBSD)
695 KernelZeroFlagVal = 0x0002;
696 else if (OS == llvm::Triple::OpenBSD)
697 KernelZeroFlagVal = 0x0008;
698 else if (OS == llvm::Triple::Linux)
700 KernelZeroFlagVal = 0x8000;
737 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
740 if (TrueState && !FalseState) {
742 return MallocMemAux(C, CE, CE->
getArg(0), ZeroVal, TrueState);
757 bool ReleasedAllocatedMemory =
false;
759 if (FD->getKind() == Decl::Function) {
763 if (FunI == II_malloc) {
769 State = ProcessZeroAllocation(C, CE, 0, State);
772 performKernelMalloc(CE, C, State);
773 if (MaybeState.hasValue())
774 State = MaybeState.getValue();
778 }
else if (FunI == II_kmalloc) {
780 performKernelMalloc(CE, C, State);
781 if (MaybeState.hasValue())
782 State = MaybeState.getValue();
785 }
else if (FunI == II_valloc) {
789 State = ProcessZeroAllocation(C, CE, 0, State);
790 }
else if (FunI == II_realloc) {
791 State = ReallocMem(C, CE,
false, State);
792 State = ProcessZeroAllocation(C, CE, 1, State);
793 }
else if (FunI == II_reallocf) {
794 State = ReallocMem(C, CE,
true, State);
795 State = ProcessZeroAllocation(C, CE, 1, State);
796 }
else if (FunI == II_calloc) {
797 State = CallocMem(C, CE, State);
798 State = ProcessZeroAllocation(C, CE, 0, State);
799 State = ProcessZeroAllocation(C, CE, 1, State);
800 }
else if (FunI == II_free) {
801 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
802 }
else if (FunI == II_strdup || FunI == II_win_strdup ||
803 FunI == II_wcsdup || FunI == II_win_wcsdup) {
804 State = MallocUpdateRefState(C, CE, State);
805 }
else if (FunI == II_strndup) {
806 State = MallocUpdateRefState(C, CE, State);
807 }
else if (FunI == II_alloca || FunI == II_win_alloca) {
810 State = ProcessZeroAllocation(C, CE, 0, State);
820 State = ProcessZeroAllocation(C, CE, 0, State);
822 else if (K == OO_Array_New) {
825 State = ProcessZeroAllocation(C, CE, 0, State);
827 else if (K == OO_Delete || K == OO_Array_Delete)
828 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
830 llvm_unreachable(
"not a new/delete operator");
831 }
else if (FunI == II_if_nameindex) {
836 }
else if (FunI == II_if_freenameindex) {
837 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
841 if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
845 for (
const auto *
I : FD->specific_attrs<OwnershipAttr>()) {
846 switch (
I->getOwnKind()) {
847 case OwnershipAttr::Returns:
848 State = MallocMemReturnsAttr(C, CE,
I, State);
850 case OwnershipAttr::Takes:
851 case OwnershipAttr::Holds:
852 State = FreeMemAttr(C, CE,
I, State);
863 const unsigned AllocationSizeArg,
868 const Expr *Arg =
nullptr;
870 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
871 Arg = CE->
getArg(AllocationSizeArg);
873 else if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
875 Arg = NE->getArraySize();
880 llvm_unreachable(
"not a CallExpr or CXXNewExpr");
884 Optional<DefinedSVal> DefArgVal =
896 std::tie(TrueState, FalseState) =
897 State->assume(SvalBuilder.
evalEQ(State, *DefArgVal, Zero));
899 if (TrueState && !FalseState) {
905 const RefState *RS = State->get<RegionState>(Sym);
907 if (RS->isAllocated())
908 return TrueState->set<RegionState>(Sym,
909 RefState::getAllocatedOfSizeZero(RS));
917 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
928 while (!PointeeType.isNull()) {
929 Result = PointeeType;
947 for (
const auto *CtorParam : CtorD->
parameters()) {
950 if (CtorParamPointeeT.
isNull())
962 void MallocChecker::checkPostStmt(
const CXXNewExpr *NE,
969 checkUseAfterFree(Sym, C, *
I);
983 State = MallocUpdateRefState(C, NE, State, NE->
isArray() ? AF_CXXNewArray
985 State = ProcessZeroAllocation(C, NE, 0, State);
992 if (!ChecksEnabled[CK_NewDeleteChecker])
1000 bool ReleasedAllocated;
1002 false, ReleasedAllocated);
1014 return FirstSlot ==
"dataWithBytesNoCopy" ||
1015 FirstSlot ==
"initWithBytesNoCopy" ||
1016 FirstSlot ==
"initWithCharactersNoCopy";
1023 for (
unsigned i = 1; i < S.
getNumArgs(); ++i)
1025 return !Call.getArgSVal(i).isZeroConstant();
1030 void MallocChecker::checkPostObjCMessage(
const ObjCMethodCall &Call,
1042 bool ReleasedAllocatedMemory;
1045 true, ReleasedAllocatedMemory,
1053 const OwnershipAttr *Att,
1058 if (Att->getModule() != II_malloc)
1061 OwnershipAttr::args_iterator
I = Att->args_begin(), E = Att->args_end();
1077 Init, State, Family);
1103 State = State->bindDefault(RetVal, Init);
1107 dyn_cast_or_null<SymbolicRegion>(RetVal.
getAsRegion());
1110 if (Optional<DefinedOrUnknownSVal> DefinedSize =
1115 svalBuilder.
evalEQ(State, Extent, *DefinedSize);
1117 State = State->assume(extentMatchesSize,
true);
1121 return MallocUpdateRefState(C, CE, State, Family);
1142 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1147 const OwnershipAttr *Att,
1152 if (Att->getModule() != II_malloc)
1155 bool ReleasedAllocated =
false;
1157 for (
const auto &Arg : Att->args()) {
1159 Att->getOwnKind() == OwnershipAttr::Holds,
1172 bool &ReleasedAllocated,
1173 bool ReturnsNullOnFailure)
const {
1180 return FreeMemAux(C, CE->
getArg(Num), CE,
State, Hold,
1181 ReleasedAllocated, ReturnsNullOnFailure);
1188 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1190 assert(*Ret &&
"We should not store the null return symbol");
1193 RetStatusSymbol = *Ret;
1200 const Stmt *S)
const {
1204 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1212 if (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Any))
1215 if (isStandardNewDelete(FD, Ctx)) {
1217 if (Kind == OO_New || Kind == OO_Delete)
1219 else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
1220 return AF_CXXNewArray;
1223 if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
1224 return AF_IfNameIndex;
1226 if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
1232 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
1233 return NE->
isArray() ? AF_CXXNewArray : AF_CXXNew;
1236 return DE->
isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
1238 if (isa<ObjCMessageExpr>(S))
1244 bool MallocChecker::printAllocDeallocName(raw_ostream &os,
CheckerContext &C,
1245 const Expr *E)
const {
1246 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1253 if (!FD->isOverloadedOperator())
1259 if (Msg->isInstanceMessage())
1263 Msg->getSelector().print(os);
1267 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1284 void MallocChecker::printExpectedAllocName(raw_ostream &os,
CheckerContext &C,
1285 const Expr *E)
const {
1289 case AF_Malloc: os <<
"malloc()";
return;
1290 case AF_CXXNew: os <<
"'new'";
return;
1291 case AF_CXXNewArray: os <<
"'new[]'";
return;
1292 case AF_IfNameIndex: os <<
"'if_nameindex()'";
return;
1294 case AF_None: llvm_unreachable(
"not a deallocation expression");
1298 void MallocChecker::printExpectedDeallocName(raw_ostream &os,
1301 case AF_Malloc: os <<
"free()";
return;
1302 case AF_CXXNew: os <<
"'delete'";
return;
1303 case AF_CXXNewArray: os <<
"'delete[]'";
return;
1304 case AF_IfNameIndex: os <<
"'if_freenameindex()'";
return;
1306 case AF_None: llvm_unreachable(
"suspicious argument");
1311 const Expr *ArgExpr,
1312 const Expr *ParentExpr,
1315 bool &ReleasedAllocated,
1316 bool ReturnsNullOnFailure)
const {
1332 std::tie(notNullState, nullState) = State->assume(location);
1333 if (nullState && !notNullState)
1346 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1353 if (isa<BlockDataRegion>(R)) {
1354 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1362 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1371 if (isa<AllocaRegion>(R))
1372 ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1374 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1386 const RefState *RsBase = State->get<RegionState>(SymBase);
1387 SymbolRef PreviousRetStatusSymbol =
nullptr;
1392 if (RsBase->getAllocationFamily() == AF_Alloca) {
1393 ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1398 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1400 ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
1401 SymBase, PreviousRetStatusSymbol);
1406 }
else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
1407 RsBase->isEscaped()) {
1410 bool DeallocMatchesAlloc =
1411 RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1412 if (!DeallocMatchesAlloc) {
1413 ReportMismatchedDealloc(C, ArgExpr->getSourceRange(),
1414 ParentExpr, RsBase, SymBase, Hold);
1424 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1425 ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1432 ReleasedAllocated = (RsBase !=
nullptr) && (RsBase->isAllocated() ||
1433 RsBase->isAllocatedOfSizeZero());
1436 State = State->remove<FreeReturnValue>(SymBase);
1440 if (ReturnsNullOnFailure) {
1443 if (RetStatusSymbol) {
1445 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1450 : getAllocationFamily(C, ParentExpr);
1453 return State->set<RegionState>(SymBase,
1454 RefState::getRelinquished(Family,
1457 return State->set<RegionState>(SymBase,
1458 RefState::getReleased(Family, ParentExpr));
1461 Optional<MallocChecker::CheckKind>
1463 bool IsALeakCheck)
const {
1467 case AF_IfNameIndex: {
1468 if (ChecksEnabled[CK_MallocChecker])
1469 return CK_MallocChecker;
1471 return Optional<MallocChecker::CheckKind>();
1474 case AF_CXXNewArray: {
1476 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
1477 return CK_NewDeleteLeaksChecker;
1480 if (ChecksEnabled[CK_NewDeleteChecker])
1481 return CK_NewDeleteChecker;
1483 return Optional<MallocChecker::CheckKind>();
1486 llvm_unreachable(
"no family");
1489 llvm_unreachable(
"unhandled family");
1492 Optional<MallocChecker::CheckKind>
1494 const Stmt *AllocDeallocStmt,
1495 bool IsALeakCheck)
const {
1496 return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
1500 Optional<MallocChecker::CheckKind>
1502 bool IsALeakCheck)
const {
1503 if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym))
1504 return CK_MallocChecker;
1506 const RefState *RS = C.
getState()->get<RegionState>(Sym);
1508 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
1511 bool MallocChecker::SummarizeValue(raw_ostream &os,
SVal V) {
1513 os <<
"an integer (" << IntVal->getValue() <<
")";
1515 os <<
"a constant address (" << ConstAddr->getValue() <<
")";
1517 os <<
"the address of the label '" << Label->getLabel()->getName() <<
"'";
1524 bool MallocChecker::SummarizeRegion(raw_ostream &os,
1527 case MemRegion::FunctionCodeRegionKind: {
1528 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1530 os <<
"the address of the function '" << *FD <<
'\'';
1532 os <<
"the address of a function";
1535 case MemRegion::BlockCodeRegionKind:
1538 case MemRegion::BlockDataRegionKind:
1545 if (isa<StackLocalsSpaceRegion>(MS)) {
1554 os <<
"the address of the local variable '" << VD->
getName() <<
"'";
1556 os <<
"the address of a local stack variable";
1560 if (isa<StackArgumentsSpaceRegion>(MS)) {
1569 os <<
"the address of the parameter '" << VD->
getName() <<
"'";
1571 os <<
"the address of a parameter";
1575 if (isa<GlobalsSpaceRegion>(MS)) {
1584 if (VD->isStaticLocal())
1585 os <<
"the address of the static variable '" << VD->
getName() <<
"'";
1587 os <<
"the address of the global variable '" << VD->getName() <<
"'";
1589 os <<
"the address of a global variable";
1600 const Expr *DeallocExpr)
const {
1602 if (!ChecksEnabled[CK_MallocChecker] &&
1603 !ChecksEnabled[CK_NewDeleteChecker])
1606 Optional<MallocChecker::CheckKind> CheckKind =
1607 getCheckIfTracked(C, DeallocExpr);
1608 if (!CheckKind.hasValue())
1612 if (!BT_BadFree[*CheckKind])
1613 BT_BadFree[*CheckKind].reset(
1614 new BugType(CheckNames[*CheckKind],
"Bad free",
"Memory Error"));
1617 llvm::raw_svector_ostream os(buf);
1620 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1621 MR = ER->getSuperRegion();
1623 os <<
"Argument to ";
1624 if (!printAllocDeallocName(os, C, DeallocExpr))
1625 os <<
"deallocator";
1628 bool Summarized = MR ? SummarizeRegion(os, MR)
1629 : SummarizeValue(os, ArgVal);
1631 os <<
", which is not memory allocated by ";
1633 os <<
"not memory allocated by ";
1635 printExpectedAllocName(os, C, DeallocExpr);
1637 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
1638 R->markInteresting(MR);
1647 Optional<MallocChecker::CheckKind> CheckKind;
1649 if (ChecksEnabled[CK_MallocChecker])
1650 CheckKind = CK_MallocChecker;
1651 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
1652 CheckKind = CK_MismatchedDeallocatorChecker;
1657 if (!BT_FreeAlloca[*CheckKind])
1658 BT_FreeAlloca[*CheckKind].reset(
1659 new BugType(CheckNames[*CheckKind],
"Free alloca()",
"Memory Error"));
1661 auto R = llvm::make_unique<BugReport>(
1662 *BT_FreeAlloca[*CheckKind],
1663 "Memory allocated by alloca() should not be deallocated", N);
1672 const Expr *DeallocExpr,
1675 bool OwnershipTransferred)
const {
1677 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
1681 if (!BT_MismatchedDealloc)
1682 BT_MismatchedDealloc.reset(
1683 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
1684 "Bad deallocator",
"Memory Error"));
1687 llvm::raw_svector_ostream os(buf);
1689 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1691 llvm::raw_svector_ostream AllocOs(AllocBuf);
1693 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1695 if (OwnershipTransferred) {
1696 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1697 os << DeallocOs.str() <<
" cannot";
1701 os <<
" take ownership of memory";
1703 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1704 os <<
" allocated by " << AllocOs.str();
1707 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1708 os <<
" allocated by " << AllocOs.str();
1710 os <<
" should be deallocated by ";
1711 printExpectedDeallocName(os, RS->getAllocationFamily());
1713 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1714 os <<
", not " << DeallocOs.str();
1717 auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
1718 R->markInteresting(Sym);
1720 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1727 const Expr *AllocExpr)
const {
1730 if (!ChecksEnabled[CK_MallocChecker] &&
1731 !ChecksEnabled[CK_NewDeleteChecker])
1734 Optional<MallocChecker::CheckKind> CheckKind =
1735 getCheckIfTracked(C, AllocExpr);
1736 if (!CheckKind.hasValue())
1743 if (!BT_OffsetFree[*CheckKind])
1744 BT_OffsetFree[*CheckKind].reset(
1745 new BugType(CheckNames[*CheckKind],
"Offset free",
"Memory Error"));
1748 llvm::raw_svector_ostream os(buf);
1750 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1753 assert(MR &&
"Only MemRegion based symbols can have offset free errors");
1759 "Only symbols with a valid offset can have offset free errors");
1763 os <<
"Argument to ";
1764 if (!printAllocDeallocName(os, C, DeallocExpr))
1765 os <<
"deallocator";
1766 os <<
" is offset by "
1769 << ((
abs(offsetBytes) > 1) ?
"bytes" :
"byte")
1770 <<
" from the start of ";
1771 if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1772 os <<
"memory allocated by " << AllocNameOs.str();
1774 os <<
"allocated memory";
1776 auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
1785 if (!ChecksEnabled[CK_MallocChecker] &&
1786 !ChecksEnabled[CK_NewDeleteChecker])
1789 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1790 if (!CheckKind.hasValue())
1794 if (!BT_UseFree[*CheckKind])
1795 BT_UseFree[*CheckKind].reset(
new BugType(
1796 CheckNames[*CheckKind],
"Use-after-free",
"Memory Error"));
1798 auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
1799 "Use of memory after it is freed", N);
1801 R->markInteresting(Sym);
1803 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1812 if (!ChecksEnabled[CK_MallocChecker] &&
1813 !ChecksEnabled[CK_NewDeleteChecker])
1816 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1817 if (!CheckKind.hasValue())
1821 if (!BT_DoubleFree[*CheckKind])
1822 BT_DoubleFree[*CheckKind].reset(
1823 new BugType(CheckNames[*CheckKind],
"Double free",
"Memory Error"));
1825 auto R = llvm::make_unique<BugReport>(
1826 *BT_DoubleFree[*CheckKind],
1827 (Released ?
"Attempt to free released memory"
1828 :
"Attempt to free non-owned memory"),
1831 R->markInteresting(Sym);
1833 R->markInteresting(PrevSym);
1834 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1841 if (!ChecksEnabled[CK_NewDeleteChecker])
1844 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1845 if (!CheckKind.hasValue())
1849 if (!BT_DoubleDelete)
1850 BT_DoubleDelete.reset(
new BugType(CheckNames[CK_NewDeleteChecker],
1851 "Double delete",
"Memory Error"));
1853 auto R = llvm::make_unique<BugReport>(
1854 *BT_DoubleDelete,
"Attempt to delete released memory", N);
1856 R->markInteresting(Sym);
1857 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1866 if (!ChecksEnabled[CK_MallocChecker] &&
1867 !ChecksEnabled[CK_NewDeleteChecker])
1870 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1872 if (!CheckKind.hasValue())
1876 if (!BT_UseZerroAllocated[*CheckKind])
1877 BT_UseZerroAllocated[*CheckKind].reset(
new BugType(
1878 CheckNames[*CheckKind],
"Use of zero allocated",
"Memory Error"));
1880 auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
1881 "Use of zero-allocated memory", N);
1885 R->markInteresting(Sym);
1886 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1904 SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
1912 svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
1920 SVal Arg1ValG = State->getSVal(Arg1, LCtx);
1927 svalBuilder.evalEQ(State, Arg1Val,
1928 svalBuilder.makeIntValWithPtrWidth(0,
false));
1931 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
1933 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
1936 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
1937 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
1941 if ( PrtIsNull && !SizeIsZero) {
1947 if (PrtIsNull && SizeIsZero)
1953 SVal RetVal = State->getSVal(CE, LCtx);
1955 if (!FromPtr || !ToPtr)
1958 bool ReleasedAllocated =
false;
1963 false, ReleasedAllocated)){
1973 FreeMemAux(C, CE, State, 0,
false, ReleasedAllocated)) {
1982 Kind = RPIsFreeOnFailure;
1983 else if (!ReleasedAllocated)
1984 Kind = RPDoNotTrackAfterFailure;
1988 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
1989 ReallocPair(FromPtr, Kind));
1992 return stateRealloc;
2007 SVal count = State->getSVal(CE->
getArg(0), LCtx);
2008 SVal elementSize = State->getSVal(CE->
getArg(1), LCtx);
2009 SVal TotalSize = svalBuilder.
evalBinOp(State, BO_Mul, count, elementSize,
2013 return MallocMemAux(C, CE, TotalSize, zeroVal, State);
2023 const MemRegion *ReferenceRegion =
nullptr;
2027 if (!State->get<RegionState>(Sym))
2032 if (!ReferenceRegion) {
2034 SVal Val = State->getSVal(MR);
2041 ReferenceRegion = MR;
2049 if (NContext == LeakContext ||
2055 return LeakInfo(AllocNode, ReferenceRegion);
2061 if (!ChecksEnabled[CK_MallocChecker] &&
2062 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2065 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2066 assert(RS &&
"cannot leak an untracked symbol");
2069 if (Family == AF_Alloca)
2072 Optional<MallocChecker::CheckKind>
2073 CheckKind = getCheckIfTracked(Family,
true);
2075 if (!CheckKind.hasValue())
2079 if (!BT_Leak[*CheckKind]) {
2080 BT_Leak[*CheckKind].reset(
2081 new BugType(CheckNames[*CheckKind],
"Memory leak",
"Memory Error"));
2087 BT_Leak[*CheckKind]->setSuppressOnSink(
true);
2096 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2099 const Stmt *AllocationStmt =
nullptr;
2101 AllocationStmt = Exit->getCalleeContext()->getCallSite();
2103 AllocationStmt = SP->getStmt();
2110 llvm::raw_svector_ostream os(buf);
2112 os <<
"Potential leak of memory pointed to by ";
2115 os <<
"Potential memory leak";
2118 auto R = llvm::make_unique<BugReport>(
2119 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2121 R->markInteresting(Sym);
2122 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym,
true));
2126 void MallocChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
2133 RegionStateTy RS = state->get<RegionState>();
2134 RegionStateTy::Factory &F = state->get_context<RegionState>();
2138 if (SymReaper.
isDead(I->first)) {
2139 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2140 Errors.push_back(I->first);
2142 RS = F.remove(RS, I->first);
2148 ReallocPairsTy RP = state->get<ReallocPairs>();
2150 if (SymReaper.
isDead(I->first) ||
2151 SymReaper.
isDead(I->second.ReallocatedSym)) {
2152 state = state->remove<ReallocPairs>(I->first);
2157 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2159 if (SymReaper.
isDead(I->first) ||
2160 SymReaper.
isDead(I->second)) {
2161 state = state->remove<FreeReturnValue>(I->first);
2167 if (!Errors.empty()) {
2172 I = Errors.begin(), E = Errors.end(); I !=
E; ++
I) {
2173 reportLeak(*I, N, C);
2181 void MallocChecker::checkPreCall(
const CallEvent &Call,
2185 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2186 if (!Sym || checkDoubleDelete(Sym, C))
2197 if (ChecksEnabled[CK_MallocChecker] &&
2198 (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
2199 isCMemFunction(FD, Ctx, AF_IfNameIndex,
2200 MemoryOperationKind::MOK_Free)))
2203 if (ChecksEnabled[CK_NewDeleteChecker] &&
2204 isStandardNewDelete(FD, Ctx))
2210 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2211 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2216 for (
unsigned I = 0, E = Call.
getNumArgs(); I !=
E; ++
I) {
2222 if (checkUseAfterFree(Sym, C, Call.
getArgExpr(I)))
2242 if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
2245 Sym = BMR->getSymbol();
2249 checkUseAfterFree(Sym, C, E);
2255 void MallocChecker::checkPostStmt(
const BlockExpr *BE,
2265 cast<BlockDataRegion>(state->getSVal(BE,
2278 for ( ; I !=
E; ++
I) {
2279 const VarRegion *VR = I.getCapturedRegion();
2283 Regions.push_back(VR);
2287 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2288 Regions.data() + Regions.size()).getState();
2294 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2295 return (RS && RS->isReleased());
2299 const Stmt *S)
const {
2301 if (isReleased(Sym, C)) {
2302 ReportUseAfterFree(C, S->getSourceRange(), Sym);
2310 const Stmt *S)
const {
2313 if (
const RefState *RS = C.
getState()->get<RegionState>(Sym)) {
2314 if (RS->isAllocatedOfSizeZero())
2315 ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
2317 else if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
2318 ReportUseZeroAllocated(C, S->getSourceRange(), Sym);
2324 if (isReleased(Sym, C)) {
2325 ReportDoubleDelete(C, Sym);
2332 void MallocChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
2336 checkUseAfterFree(Sym, C, S);
2337 checkUseZeroAllocated(Sym, C, S);
2345 bool Assumption)
const {
2346 RegionStateTy RS = state->get<RegionState>();
2352 state = state->remove<RegionState>(I.getKey());
2357 ReallocPairsTy RP = state->get<ReallocPairs>();
2365 SymbolRef ReallocSym = I.getData().ReallocatedSym;
2366 if (
const RefState *RS = state->get<RegionState>(ReallocSym)) {
2367 if (RS->isReleased()) {
2368 if (I.getData().Kind == RPToBeFreedAfterFailure)
2369 state = state->set<RegionState>(ReallocSym,
2370 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
2371 else if (I.getData().Kind == RPDoNotTrackAfterFailure)
2372 state = state->remove<RegionState>(ReallocSym);
2374 assert(I.getData().Kind == RPIsFreeOnFailure);
2377 state = state->remove<ReallocPairs>(I.getKey());
2383 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
2388 EscapingSymbol =
nullptr;
2394 if (!(isa<SimpleFunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
2398 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
2414 return *FreeWhenDone;
2420 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
2421 if (FirstSlot.endswith(
"NoCopy"))
2428 if (FirstSlot.startswith(
"addPointer") ||
2429 FirstSlot.startswith(
"insertPointer") ||
2430 FirstSlot.startswith(
"replacePointer") ||
2431 FirstSlot.equals(
"valueWithPointer")) {
2438 if (Msg->getMethodFamily() ==
OMF_init) {
2439 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
2449 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
2453 ASTContext &ASTC = State->getStateManager().getContext();
2457 if (isMemFunction(FD, ASTC))
2468 StringRef FName = II->
getName();
2472 if (FName.endswith(
"NoCopy")) {
2476 for (
unsigned i = 1; i < Call->
getNumArgs(); ++i) {
2478 if (
const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
2479 StringRef DeallocatorName = DE->getFoundDecl()->getName();
2480 if (DeallocatorName ==
"kCFAllocatorNull")
2491 if (FName ==
"funopen")
2498 if (FName ==
"setbuf" || FName ==
"setbuffer" ||
2499 FName ==
"setlinebuf" || FName ==
"setvbuf") {
2502 if (
const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
2503 if (
const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
2504 if (D->getCanonicalDecl()->getName().find(
"std") != StringRef::npos)
2514 if (FName ==
"CGBitmapContextCreate" ||
2515 FName ==
"CGBitmapContextCreateWithData" ||
2516 FName ==
"CVPixelBufferCreateWithBytes" ||
2517 FName ==
"CVPixelBufferCreateWithPlanarBytes" ||
2518 FName ==
"OSAtomicEnqueue") {
2522 if (FName ==
"postEvent" &&
2527 if (FName ==
"postEvent" &&
2549 return (RS->getAllocationFamily() == AF_CXXNewArray ||
2550 RS->getAllocationFamily() == AF_CXXNew);
2557 return checkPointerEscapeAux(State, Escaped, Call, Kind, &
retTrue);
2564 return checkPointerEscapeAux(State, Escaped, Call, Kind,
2572 bool(*CheckRefState)(
const RefState*))
const {
2577 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
2583 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2588 if (EscapingSymbol && EscapingSymbol != sym)
2591 if (
const RefState *RS = State->get<RegionState>(sym)) {
2592 if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
2593 CheckRefState(RS)) {
2594 State = State->remove<RegionState>(sym);
2595 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2604 ReallocPairsTy currMap = currState->get<ReallocPairs>();
2605 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2610 if (!currMap.lookup(sym))
2618 MallocChecker::MallocBugVisitor::VisitNode(
const ExplodedNode *N,
2625 const RefState *RS = state->get<RegionState>(Sym);
2626 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2630 const Stmt *S =
nullptr;
2631 const char *Msg =
nullptr;
2639 S = Exit->getCalleeContext()->getCallSite();
2640 }
else if (Optional<BlockEdge> Edge = ProgLoc.
getAs<
BlockEdge>()) {
2643 S = Edge->getSrc()->getTerminator();
2653 if (Mode == Normal) {
2654 if (isAllocated(RS, RSPrev, S)) {
2655 Msg =
"Memory is allocated";
2657 "Returned allocated memory");
2658 }
else if (isReleased(RS, RSPrev, S)) {
2659 Msg =
"Memory is released";
2661 "Returning; memory was released");
2662 }
else if (isRelinquished(RS, RSPrev, S)) {
2663 Msg =
"Memory ownership is transferred";
2665 }
else if (isReallocFailedCheck(RS, RSPrev, S)) {
2666 Mode = ReallocationFailed;
2667 Msg =
"Reallocation failed";
2668 StackHint =
new StackHintGeneratorForReallocationFailed(Sym,
2669 "Reallocation failed");
2673 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
2674 "We only support one failed realloc at a time.");
2676 FailedReallocSymbol = sym;
2681 }
else if (Mode == ReallocationFailed) {
2682 assert(FailedReallocSymbol &&
"No symbol to look for.");
2685 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
2687 Msg =
"Attempt to reallocate memory";
2689 "Returned reallocated memory");
2690 FailedReallocSymbol =
nullptr;
2705 void MallocChecker::printState(raw_ostream &Out,
ProgramStateRef State,
2706 const char *NL,
const char *Sep)
const {
2708 RegionStateTy RS = State->get<RegionState>();
2710 if (!RS.isEmpty()) {
2711 Out << Sep <<
"MallocChecker :" << NL;
2713 const RefState *RefS = State->get<RegionState>(I.getKey());
2715 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
2716 if (!CheckKind.hasValue())
2717 CheckKind = getCheckIfTracked(Family,
true);
2719 I.getKey()->dumpToStream(Out);
2721 I.getData().dump(Out);
2722 if (CheckKind.hasValue())
2723 Out <<
" (" << CheckNames[*CheckKind].getName() <<
")";
2733 "Optimistic",
false, checker);
2734 checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] =
true;
2735 checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
2739 if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker])
2740 checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] =
true;
2743 #define REGISTER_CHECKER(name) \
2744 void ento::register##name(CheckerManager &mgr) { \
2745 registerCStringCheckerBasic(mgr); \
2746 MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
2747 checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
2748 "Optimistic", false, checker); \
2749 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
2750 checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
bool isInSystemHeader() const
Returns true if the callee is known to be from a system header.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool hasDeadSymbols() const
bool operator==(CanQual< T > x, CanQual< U > y)
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
A helper class which wraps a boolean value set to false by default.
virtual bool argumentsMayEscape() const
Returns true if any of the arguments are known to escape to long- term storage, even if this method w...
const StackFrameContext * getStackFrame() const
Defines the SourceManager interface.
ConstExprIterator const_arg_iterator
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
__DEVICE__ long long abs(long long __n)
const RegionTy * getAs() const
Constructs a Stack hint for the given symbol.
Represents a call to a C++ constructor.
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
Represents a C++ constructor within a class.
Value representing integer constant.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
referenced_vars_iterator referenced_vars_begin() const
bool hasCaptures() const
hasCaptures - True if this block (or its nested blocks) captures anything of local storage from its e...
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
const MemRegion * getBaseRegion() const
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
referenced_vars_iterator referenced_vars_end() const
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
const MemSpaceRegion * getMemorySpace() const
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call)
One of these records is kept for each identifier that is lexed.
MemRegionManager & getRegionManager()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
const VarDecl * getDecl() const
static bool isLocType(QualType T)
void registerCStringCheckerBasic(CheckerManager &Mgr)
Register the checker which evaluates CString API calls.
BlockDataRegion - A region that represents a block instance.
Represents any expression that calls an Objective-C method.
const TargetInfo & getTargetInfo() const
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
SymbolRef getSymbol() const
bool isUnknownOrUndef() const
bool isParentOf(const LocationContext *LC) const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
bool isVariadic() const
Whether this function is variadic.
StringRef getDescription() const
detail::InMemoryDirectory::const_iterator I
Represent a region's offset within the top level base region.
static bool didPreviousFreeFail(ProgramStateRef State, SymbolRef Sym, SymbolRef &RetStatusSymbol)
Checks if the previous call to free on the given symbol failed - if free failed, returns true...
arg_iterator placement_arg_end()
const MemRegion * getSuperRegion() const
const LocationContext * getLocationContext() const
FunctionDecl * getOperatorDelete() const
Represents a non-static C++ member function call, no matter how it is written.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const MemRegion * StripCasts(bool StripBaseCasts=true) const
Represents a point when we finish the call exit sequence (for inlined call).
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SymbolicRegion - A special, "non-concrete" region.
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Expr - This represents one expression.
const ProgramStateRef & getState() const
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
unsigned getNumArgs() const
CheckName getCurrentCheckName() const
Represents an implicit call to a C++ destructor.
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override
getExtent - Returns the size of the region in bytes.
static bool retTrue(const RefState *RS)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
ParentMap & getParentMap() const
bool hasSymbolicOffset() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
The pointer has been passed to a function call directly.
Represents a call to any sort of function that might have a FunctionDecl.
const ParmVarDecl * getParamDecl(unsigned i) const
SymbolManager & getSymbolManager()
QualType getAllocatedType() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
An expression that sends a message to the given Objective-C object or class.
const IdentifierInfo * getBaseTypeIdentifier() const
Retrieves a pointer to the name of the base type.
void markInteresting(SymbolRef sym)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
The result type of a method or function.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
bool isConsumedExpr(Expr *E) const
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
unsigned getNumParams() const
getNumParams - Return the number of parameters this function must have based on its FunctionType...
const TemplateArgument * iterator
const StackFrameContext * getCurrentStackFrame() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
ASTContext & getContext()
ArrayRef< ParmVarDecl * > parameters() const
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Selector getSelector() const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
const Decl * getDecl() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
A class responsible for cleaning up unused symbols.
static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState)
DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, const LocationContext *LCtx, unsigned Count)
Conjure a symbol representing heap allocated memory region.
const BlockDecl * getBlockDecl() const
static bool treatUnusedNewEscaped(const CXXNewExpr *NE)
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
ASTContext & getASTContext()
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
static QualType getDeepPointeeType(QualType T)
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
unsigned getNumPlacementArgs() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
const Expr * getRetValue() const
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Represents an abstract call to a function or method along a particular path.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalyzerOptions & getAnalyzerOptions()
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
FunctionDecl * getOperatorNew() const
#define REGISTER_CHECKER(name)
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword...
int64_t getOffset() const
static Optional< bool > getFreeWhenDoneArg(const ObjCMethodCall &Call)
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
uint64_t getCharWidth() const
Return the size of the character type, in bits.
arg_iterator placement_arg_begin()
std::string getQualifiedNameAsString() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
const Expr * getArgExpr(unsigned Index) const override
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
pred_iterator pred_begin()
SourceManager & getSourceManager()
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
SValBuilder & getSValBuilder()
Defines the clang::TargetInfo interface.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ElementRegin is used to represent both array elements and casts.
A reference to a declared variable, function, enum, etc.
static const MemRegion * getLocationRegionIfPostStore(const ExplodedNode *N)
If the given node corresponds to a PostStore program point, retrieve the location region as it was ut...
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
This class provides an interface through which checkers can create individual bug reports...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
virtual const ObjCMessageExpr * getOriginExpr() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SourceManager & getSourceManager()
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any...