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), II_g_malloc(
nullptr),
179 II_g_malloc0(
nullptr), II_g_realloc(
nullptr), II_g_try_malloc(
nullptr),
180 II_g_try_malloc0(
nullptr), II_g_try_realloc(
nullptr),
181 II_g_free(
nullptr), II_g_memdup(
nullptr), II_g_malloc_n(
nullptr),
182 II_g_malloc0_n(
nullptr), II_g_realloc_n(
nullptr),
183 II_g_try_malloc_n(
nullptr), II_g_try_malloc0_n(
nullptr),
184 II_g_try_realloc_n(
nullptr) {}
191 CK_NewDeleteLeaksChecker,
192 CK_MismatchedDeallocatorChecker,
196 enum class MemoryOperationKind {
216 bool Assumption)
const;
217 void checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
230 const char *NL,
const char *Sep)
const override;
233 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
234 mutable std::unique_ptr<BugType> BT_DoubleDelete;
235 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
236 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
237 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
238 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
239 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
240 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
241 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
242 mutable IdentifierInfo *II_alloca, *II_win_alloca, *II_malloc, *II_free,
243 *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
244 *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
245 *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
246 *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,
247 *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,
248 *II_g_try_realloc, *II_g_free, *II_g_memdup,
249 *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,
250 *II_g_try_malloc_n, *II_g_try_malloc0_n,
263 const Expr *E)
const;
268 const Expr *DeallocExpr)
const;
271 void printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family)
const;
280 MemoryOperationKind MemKind)
const;
286 const unsigned AllocationSizeArg,
291 const OwnershipAttr* Att,
317 const OwnershipAttr* Att,
322 bool &ReleasedAllocated,
323 bool ReturnsNullOnFailure =
false)
const;
325 const Expr *ParentExpr,
328 bool &ReleasedAllocated,
329 bool ReturnsNullOnFailure =
false)
const;
332 bool FreesMemOnFailure,
334 bool SuffixWithN =
false)
const;
336 const Expr *BlockBytes);
346 const Stmt *S)
const;
360 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
const CallEvent *Call,
369 bool(*CheckRefState)(
const RefState*))
const;
376 bool IsALeakCheck =
false)
const;
378 const Stmt *AllocDeallocStmt,
379 bool IsALeakCheck =
false)
const;
381 bool IsALeakCheck =
false)
const;
383 static bool SummarizeValue(raw_ostream &os,
SVal V);
384 static bool SummarizeRegion(raw_ostream &os,
const MemRegion *MR);
386 const Expr *DeallocExpr)
const;
390 const Expr *DeallocExpr,
const RefState *RS,
391 SymbolRef Sym,
bool OwnershipTransferred)
const;
393 const Expr *DeallocExpr,
394 const Expr *AllocExpr =
nullptr)
const;
418 class MallocBugVisitor final
421 enum NotificationMode {
430 NotificationMode Mode;
438 MallocBugVisitor(
SymbolRef S,
bool isLeak =
false)
439 : Sym(S), Mode(Normal), FailedReallocSymbol(
nullptr), IsLeak(isLeak) {}
441 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
447 inline bool isAllocated(
const RefState *S,
const RefState *SPrev,
450 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
451 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
452 (!SPrev || !(SPrev->isAllocated() ||
453 SPrev->isAllocatedOfSizeZero())));
456 inline bool isReleased(
const RefState *S,
const RefState *SPrev,
459 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) &&
460 (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
463 inline bool isRelinquished(
const RefState *S,
const RefState *SPrev,
466 return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
467 isa<ObjCPropertyRefExpr>(Stmt)) &&
468 (S && S->isRelinquished()) &&
469 (!SPrev || !SPrev->isRelinquished()));
472 inline bool isReallocFailedCheck(
const RefState *S,
const RefState *SPrev,
478 return ((!Stmt || !isa<CallExpr>(Stmt)) &&
479 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
480 (SPrev && !(SPrev->isAllocated() ||
481 SPrev->isAllocatedOfSizeZero())));
484 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
489 std::unique_ptr<PathDiagnosticPiece>
499 return llvm::make_unique<PathDiagnosticEventPiece>(L, BR.
getDescription(),
504 class StackHintGeneratorForReallocationFailed
507 StackHintGeneratorForReallocationFailed(
SymbolRef S, StringRef M)
510 std::string getMessageForArg(
const Expr *ArgE,
511 unsigned ArgIndex)
override {
516 llvm::raw_svector_ostream os(buf);
518 os <<
"Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
519 <<
" parameter failed";
525 return "Reallocation of returned value failed";
547 bool VisitSymbol(
SymbolRef sym)
override {
548 state = state->remove<RegionState>(sym);
554 void MallocChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
561 II_reallocf = &Ctx.
Idents.
get(
"reallocf");
568 II_if_nameindex = &Ctx.
Idents.
get(
"if_nameindex");
569 II_if_freenameindex = &Ctx.
Idents.
get(
"if_freenameindex");
572 II_win_strdup = &Ctx.
Idents.
get(
"_strdup");
573 II_win_wcsdup = &Ctx.
Idents.
get(
"_wcsdup");
574 II_win_alloca = &Ctx.
Idents.
get(
"_alloca");
577 II_g_malloc = &Ctx.
Idents.
get(
"g_malloc");
578 II_g_malloc0 = &Ctx.
Idents.
get(
"g_malloc0");
579 II_g_realloc = &Ctx.
Idents.
get(
"g_realloc");
580 II_g_try_malloc = &Ctx.
Idents.
get(
"g_try_malloc");
581 II_g_try_malloc0 = &Ctx.
Idents.
get(
"g_try_malloc0");
582 II_g_try_realloc = &Ctx.
Idents.
get(
"g_try_realloc");
584 II_g_memdup = &Ctx.
Idents.
get(
"g_memdup");
585 II_g_malloc_n = &Ctx.
Idents.
get(
"g_malloc_n");
586 II_g_malloc0_n = &Ctx.
Idents.
get(
"g_malloc0_n");
587 II_g_realloc_n = &Ctx.
Idents.
get(
"g_realloc_n");
588 II_g_try_malloc_n = &Ctx.
Idents.
get(
"g_try_malloc_n");
589 II_g_try_malloc0_n = &Ctx.
Idents.
get(
"g_try_malloc0_n");
590 II_g_try_realloc_n = &Ctx.
Idents.
get(
"g_try_realloc_n");
594 if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any))
597 if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
600 if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
603 if (isStandardNewDelete(FD, C))
609 bool MallocChecker::isCMemFunction(
const FunctionDecl *FD,
612 MemoryOperationKind MemKind)
const {
616 bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any ||
617 MemKind == MemoryOperationKind::MOK_Free);
618 bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any ||
619 MemKind == MemoryOperationKind::MOK_Allocate);
621 if (FD->
getKind() == Decl::Function) {
623 initIdentifierInfo(C);
625 if (Family == AF_Malloc && CheckFree) {
626 if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
631 if (Family == AF_Malloc && CheckAlloc) {
632 if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
633 FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
634 FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
635 FunI == II_win_wcsdup || FunI == II_kmalloc ||
636 FunI == II_g_malloc || FunI == II_g_malloc0 ||
637 FunI == II_g_realloc || FunI == II_g_try_malloc ||
638 FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||
639 FunI == II_g_memdup || FunI == II_g_malloc_n ||
640 FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||
641 FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||
642 FunI == II_g_try_realloc_n)
646 if (Family == AF_IfNameIndex && CheckFree) {
647 if (FunI == II_if_freenameindex)
651 if (Family == AF_IfNameIndex && CheckAlloc) {
652 if (FunI == II_if_nameindex)
656 if (Family == AF_Alloca && CheckAlloc) {
657 if (FunI == II_alloca || FunI == II_win_alloca)
662 if (Family != AF_Malloc)
665 if (IsOptimistic && FD->
hasAttrs()) {
667 OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
668 if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
671 }
else if (OwnKind == OwnershipAttr::Returns) {
685 bool MallocChecker::isStandardNewDelete(
const FunctionDecl *FD,
691 if (Kind != OO_New && Kind != OO_Array_New &&
692 Kind != OO_Delete && Kind != OO_Array_Delete)
696 if (isa<CXXMethodDecl>(FD))
703 return II->getName().equals(
"nothrow_t");
735 if (!KernelZeroFlagVal.hasValue()) {
736 if (OS == llvm::Triple::FreeBSD)
737 KernelZeroFlagVal = 0x0100;
738 else if (OS == llvm::Triple::NetBSD)
739 KernelZeroFlagVal = 0x0002;
740 else if (OS == llvm::Triple::OpenBSD)
741 KernelZeroFlagVal = 0x0008;
742 else if (OS == llvm::Triple::Linux)
744 KernelZeroFlagVal = 0x8000;
781 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
784 if (TrueState && !FalseState) {
786 return MallocMemAux(C, CE, CE->
getArg(0), ZeroVal, TrueState);
793 const Expr *BlockBytes) {
798 SVal TotalSize = SB.
evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,
812 bool ReleasedAllocatedMemory =
false;
814 if (FD->
getKind() == Decl::Function) {
818 if (FunI == II_malloc || FunI == II_g_malloc || FunI == II_g_try_malloc) {
824 State = ProcessZeroAllocation(C, CE, 0, State);
827 performKernelMalloc(CE, C, State);
828 if (MaybeState.hasValue())
829 State = MaybeState.getValue();
833 }
else if (FunI == II_kmalloc) {
837 performKernelMalloc(CE, C, State);
838 if (MaybeState.hasValue())
839 State = MaybeState.getValue();
842 }
else if (FunI == II_valloc) {
846 State = ProcessZeroAllocation(C, CE, 0, State);
847 }
else if (FunI == II_realloc || FunI == II_g_realloc ||
848 FunI == II_g_try_realloc) {
849 State = ReallocMemAux(C, CE,
false, State);
850 State = ProcessZeroAllocation(C, CE, 1, State);
851 }
else if (FunI == II_reallocf) {
852 State = ReallocMemAux(C, CE,
true, State);
853 State = ProcessZeroAllocation(C, CE, 1, State);
854 }
else if (FunI == II_calloc) {
855 State = CallocMem(C, CE, State);
856 State = ProcessZeroAllocation(C, CE, 0, State);
857 State = ProcessZeroAllocation(C, CE, 1, State);
858 }
else if (FunI == II_free || FunI == II_g_free) {
859 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
860 }
else if (FunI == II_strdup || FunI == II_win_strdup ||
861 FunI == II_wcsdup || FunI == II_win_wcsdup) {
862 State = MallocUpdateRefState(C, CE, State);
863 }
else if (FunI == II_strndup) {
864 State = MallocUpdateRefState(C, CE, State);
865 }
else if (FunI == II_alloca || FunI == II_win_alloca) {
870 State = ProcessZeroAllocation(C, CE, 0, State);
880 State = ProcessZeroAllocation(C, CE, 0, State);
882 else if (K == OO_Array_New) {
885 State = ProcessZeroAllocation(C, CE, 0, State);
887 else if (K == OO_Delete || K == OO_Array_Delete)
888 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
890 llvm_unreachable(
"not a new/delete operator");
891 }
else if (FunI == II_if_nameindex) {
896 }
else if (FunI == II_if_freenameindex) {
897 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
898 }
else if (FunI == II_g_malloc0 || FunI == II_g_try_malloc0) {
903 State = MallocMemAux(C, CE, CE->
getArg(0), zeroVal,
State);
904 State = ProcessZeroAllocation(C, CE, 0, State);
905 }
else if (FunI == II_g_memdup) {
909 State = ProcessZeroAllocation(C, CE, 1, State);
910 }
else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||
911 FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
915 if (FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
920 State = MallocMemAux(C, CE, TotalSize, Init, State);
921 State = ProcessZeroAllocation(C, CE, 0, State);
922 State = ProcessZeroAllocation(C, CE, 1, State);
923 }
else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n) {
926 State = ReallocMemAux(C, CE,
false, State,
true);
927 State = ProcessZeroAllocation(C, CE, 1, State);
928 State = ProcessZeroAllocation(C, CE, 2, State);
932 if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
937 switch (I->getOwnKind()) {
938 case OwnershipAttr::Returns:
939 State = MallocMemReturnsAttr(C, CE, I, State);
941 case OwnershipAttr::Takes:
942 case OwnershipAttr::Holds:
943 State = FreeMemAttr(C, CE, I, State);
954 const unsigned AllocationSizeArg,
959 const Expr *Arg =
nullptr;
961 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
962 Arg = CE->
getArg(AllocationSizeArg);
964 else if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
966 Arg = NE->getArraySize();
971 llvm_unreachable(
"not a CallExpr or CXXNewExpr");
987 std::tie(TrueState, FalseState) =
988 State->assume(SvalBuilder.
evalEQ(State, *DefArgVal, Zero));
990 if (TrueState && !FalseState) {
996 const RefState *RS = State->get<RegionState>(Sym);
998 if (RS->isAllocated())
999 return TrueState->set<RegionState>(Sym,
1000 RefState::getAllocatedOfSizeZero(RS));
1008 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
1019 while (!PointeeType.isNull()) {
1020 Result = PointeeType;
1038 for (
const auto *CtorParam : CtorD->
parameters()) {
1041 if (CtorParamPointeeT.
isNull())
1053 void MallocChecker::checkPostStmt(
const CXXNewExpr *NE,
1060 checkUseAfterFree(Sym, C, *I);
1074 State = MallocUpdateRefState(C, NE, State, NE->
isArray() ? AF_CXXNewArray
1076 State = addExtentSize(C, NE, State);
1077 State = ProcessZeroAllocation(C, NE, 0, State);
1098 Region = (State->getSVal(NE, LCtx))
1104 ElementCount = svalBuilder.
makeIntVal(1,
true);
1105 Region = (State->getSVal(NE, LCtx)).getAsRegion()->
getAs<
SubRegion>();
1123 State = State->assume(extentMatchesSize,
true);
1131 if (!ChecksEnabled[CK_NewDeleteChecker])
1139 bool ReleasedAllocated;
1141 false, ReleasedAllocated);
1153 return FirstSlot ==
"dataWithBytesNoCopy" ||
1154 FirstSlot ==
"initWithBytesNoCopy" ||
1155 FirstSlot ==
"initWithCharactersNoCopy";
1162 for (
unsigned i = 1; i < S.
getNumArgs(); ++i)
1164 return !Call.getArgSVal(i).isZeroConstant();
1169 void MallocChecker::checkPostObjCMessage(
const ObjCMethodCall &Call,
1181 bool ReleasedAllocatedMemory;
1184 true, ReleasedAllocatedMemory,
1192 const OwnershipAttr *Att,
1197 if (Att->getModule() != II_malloc)
1200 OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
1216 Init, State, Family);
1242 State = State->bindDefault(RetVal, Init, LCtx);
1246 dyn_cast_or_null<SymbolicRegion>(RetVal.
getAsRegion());
1254 svalBuilder.
evalEQ(State, Extent, *DefinedSize);
1256 State = State->assume(extentMatchesSize,
true);
1260 return MallocUpdateRefState(C, CE, State, Family);
1281 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1286 const OwnershipAttr *Att,
1291 if (Att->getModule() != II_malloc)
1294 bool ReleasedAllocated =
false;
1296 for (
const auto &Arg : Att->args()) {
1298 Att->getOwnKind() == OwnershipAttr::Holds,
1311 bool &ReleasedAllocated,
1312 bool ReturnsNullOnFailure)
const {
1319 return FreeMemAux(C, CE->
getArg(Num), CE,
State, Hold,
1320 ReleasedAllocated, ReturnsNullOnFailure);
1327 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1329 assert(*Ret &&
"We should not store the null return symbol");
1332 RetStatusSymbol = *Ret;
1339 const Stmt *S)
const {
1343 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1351 if (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Any))
1354 if (isStandardNewDelete(FD, Ctx)) {
1356 if (Kind == OO_New || Kind == OO_Delete)
1358 else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
1359 return AF_CXXNewArray;
1362 if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
1363 return AF_IfNameIndex;
1365 if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
1371 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
1372 return NE->
isArray() ? AF_CXXNewArray : AF_CXXNew;
1375 return DE->
isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
1377 if (isa<ObjCMessageExpr>(S))
1383 bool MallocChecker::printAllocDeallocName(raw_ostream &os,
CheckerContext &C,
1384 const Expr *E)
const {
1385 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1392 if (!FD->isOverloadedOperator())
1398 if (Msg->isInstanceMessage())
1402 Msg->getSelector().
print(os);
1406 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1423 void MallocChecker::printExpectedAllocName(raw_ostream &os,
CheckerContext &C,
1424 const Expr *E)
const {
1428 case AF_Malloc: os <<
"malloc()";
return;
1429 case AF_CXXNew: os <<
"'new'";
return;
1430 case AF_CXXNewArray: os <<
"'new[]'";
return;
1431 case AF_IfNameIndex: os <<
"'if_nameindex()'";
return;
1433 case AF_None: llvm_unreachable(
"not a deallocation expression");
1437 void MallocChecker::printExpectedDeallocName(raw_ostream &os,
1440 case AF_Malloc: os <<
"free()";
return;
1441 case AF_CXXNew: os <<
"'delete'";
return;
1442 case AF_CXXNewArray: os <<
"'delete[]'";
return;
1443 case AF_IfNameIndex: os <<
"'if_freenameindex()'";
return;
1445 case AF_None: llvm_unreachable(
"suspicious argument");
1450 const Expr *ArgExpr,
1451 const Expr *ParentExpr,
1454 bool &ReleasedAllocated,
1455 bool ReturnsNullOnFailure)
const {
1471 std::tie(notNullState, nullState) = State->assume(location);
1472 if (nullState && !notNullState)
1492 if (isa<BlockDataRegion>(R)) {
1501 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1510 if (isa<AllocaRegion>(R))
1525 const RefState *RsBase = State->get<RegionState>(SymBase);
1526 SymbolRef PreviousRetStatusSymbol =
nullptr;
1531 if (RsBase->getAllocationFamily() == AF_Alloca) {
1537 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1539 ReportDoubleFree(C, ParentExpr->
getSourceRange(), RsBase->isReleased(),
1540 SymBase, PreviousRetStatusSymbol);
1545 }
else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
1546 RsBase->isEscaped()) {
1549 bool DeallocMatchesAlloc =
1550 RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1551 if (!DeallocMatchesAlloc) {
1553 ParentExpr, RsBase, SymBase, Hold);
1563 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1564 ReportOffsetFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr,
1572 ReportFunctionPointerFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr);
1576 ReleasedAllocated = (RsBase !=
nullptr) && (RsBase->isAllocated() ||
1577 RsBase->isAllocatedOfSizeZero());
1580 State = State->remove<FreeReturnValue>(SymBase);
1584 if (ReturnsNullOnFailure) {
1587 if (RetStatusSymbol) {
1589 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1594 : getAllocationFamily(C, ParentExpr);
1597 return State->set<RegionState>(SymBase,
1598 RefState::getRelinquished(Family,
1601 return State->set<RegionState>(SymBase,
1602 RefState::getReleased(Family, ParentExpr));
1607 bool IsALeakCheck)
const {
1611 case AF_IfNameIndex: {
1612 if (ChecksEnabled[CK_MallocChecker])
1613 return CK_MallocChecker;
1618 case AF_CXXNewArray: {
1620 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
1621 return CK_NewDeleteLeaksChecker;
1624 if (ChecksEnabled[CK_NewDeleteChecker])
1625 return CK_NewDeleteChecker;
1630 llvm_unreachable(
"no family");
1633 llvm_unreachable(
"unhandled family");
1638 const Stmt *AllocDeallocStmt,
1639 bool IsALeakCheck)
const {
1640 return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
1646 bool IsALeakCheck)
const {
1647 if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym))
1648 return CK_MallocChecker;
1650 const RefState *RS = C.
getState()->get<RegionState>(Sym);
1652 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
1655 bool MallocChecker::SummarizeValue(raw_ostream &os,
SVal V) {
1657 os <<
"an integer (" << IntVal->getValue() <<
")";
1659 os <<
"a constant address (" << ConstAddr->getValue() <<
")";
1661 os <<
"the address of the label '" <<
Label->getLabel()->getName() <<
"'";
1668 bool MallocChecker::SummarizeRegion(raw_ostream &os,
1671 case MemRegion::FunctionCodeRegionKind: {
1672 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1674 os <<
"the address of the function '" << *FD <<
'\'';
1676 os <<
"the address of a function";
1679 case MemRegion::BlockCodeRegionKind:
1682 case MemRegion::BlockDataRegionKind:
1689 if (isa<StackLocalsSpaceRegion>(MS)) {
1698 os <<
"the address of the local variable '" << VD->
getName() <<
"'";
1700 os <<
"the address of a local stack variable";
1704 if (isa<StackArgumentsSpaceRegion>(MS)) {
1713 os <<
"the address of the parameter '" << VD->
getName() <<
"'";
1715 os <<
"the address of a parameter";
1719 if (isa<GlobalsSpaceRegion>(MS)) {
1728 if (VD->isStaticLocal())
1729 os <<
"the address of the static variable '" << VD->
getName() <<
"'";
1731 os <<
"the address of the global variable '" << VD->getName() <<
"'";
1733 os <<
"the address of a global variable";
1744 const Expr *DeallocExpr)
const {
1746 if (!ChecksEnabled[CK_MallocChecker] &&
1747 !ChecksEnabled[CK_NewDeleteChecker])
1751 getCheckIfTracked(C, DeallocExpr);
1752 if (!CheckKind.hasValue())
1756 if (!BT_BadFree[*CheckKind])
1757 BT_BadFree[*CheckKind].reset(
new BugType(
1761 llvm::raw_svector_ostream os(buf);
1764 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1765 MR = ER->getSuperRegion();
1767 os <<
"Argument to ";
1768 if (!printAllocDeallocName(os, C, DeallocExpr))
1769 os <<
"deallocator";
1772 bool Summarized = MR ? SummarizeRegion(os, MR)
1773 : SummarizeValue(os, ArgVal);
1775 os <<
", which is not memory allocated by ";
1777 os <<
"not memory allocated by ";
1779 printExpectedAllocName(os, C, DeallocExpr);
1781 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
1782 R->markInteresting(MR);
1793 if (ChecksEnabled[CK_MallocChecker])
1794 CheckKind = CK_MallocChecker;
1795 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
1796 CheckKind = CK_MismatchedDeallocatorChecker;
1801 if (!BT_FreeAlloca[*CheckKind])
1802 BT_FreeAlloca[*CheckKind].reset(
new BugType(
1805 auto R = llvm::make_unique<BugReport>(
1806 *BT_FreeAlloca[*CheckKind],
1807 "Memory allocated by alloca() should not be deallocated", N);
1816 const Expr *DeallocExpr,
1819 bool OwnershipTransferred)
const {
1821 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
1825 if (!BT_MismatchedDealloc)
1826 BT_MismatchedDealloc.reset(
1827 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
1831 llvm::raw_svector_ostream os(buf);
1833 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1835 llvm::raw_svector_ostream AllocOs(AllocBuf);
1837 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1839 if (OwnershipTransferred) {
1840 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1841 os << DeallocOs.str() <<
" cannot";
1845 os <<
" take ownership of memory";
1847 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1848 os <<
" allocated by " << AllocOs.str();
1851 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1852 os <<
" allocated by " << AllocOs.str();
1854 os <<
" should be deallocated by ";
1855 printExpectedDeallocName(os, RS->getAllocationFamily());
1857 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1858 os <<
", not " << DeallocOs.str();
1861 auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
1862 R->markInteresting(Sym);
1864 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1871 const Expr *AllocExpr)
const {
1874 if (!ChecksEnabled[CK_MallocChecker] &&
1875 !ChecksEnabled[CK_NewDeleteChecker])
1879 getCheckIfTracked(C, AllocExpr);
1880 if (!CheckKind.hasValue())
1887 if (!BT_OffsetFree[*CheckKind])
1888 BT_OffsetFree[*CheckKind].reset(
new BugType(
1892 llvm::raw_svector_ostream os(buf);
1894 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1897 assert(MR &&
"Only MemRegion based symbols can have offset free errors");
1903 "Only symbols with a valid offset can have offset free errors");
1907 os <<
"Argument to ";
1908 if (!printAllocDeallocName(os, C, DeallocExpr))
1909 os <<
"deallocator";
1910 os <<
" is offset by " 1913 << ((
abs(offsetBytes) > 1) ?
"bytes" :
"byte")
1914 <<
" from the start of ";
1915 if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1916 os <<
"memory allocated by " << AllocNameOs.str();
1918 os <<
"allocated memory";
1920 auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
1929 if (!ChecksEnabled[CK_MallocChecker] &&
1930 !ChecksEnabled[CK_NewDeleteChecker])
1934 if (!CheckKind.hasValue())
1938 if (!BT_UseFree[*CheckKind])
1939 BT_UseFree[*CheckKind].reset(
new BugType(
1942 auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
1943 "Use of memory after it is freed", N);
1945 R->markInteresting(Sym);
1947 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1956 if (!ChecksEnabled[CK_MallocChecker] &&
1957 !ChecksEnabled[CK_NewDeleteChecker])
1961 if (!CheckKind.hasValue())
1965 if (!BT_DoubleFree[*CheckKind])
1966 BT_DoubleFree[*CheckKind].reset(
new BugType(
1969 auto R = llvm::make_unique<BugReport>(
1970 *BT_DoubleFree[*CheckKind],
1971 (Released ?
"Attempt to free released memory" 1972 :
"Attempt to free non-owned memory"),
1975 R->markInteresting(Sym);
1977 R->markInteresting(PrevSym);
1978 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1985 if (!ChecksEnabled[CK_NewDeleteChecker])
1989 if (!CheckKind.hasValue())
1993 if (!BT_DoubleDelete)
1994 BT_DoubleDelete.reset(
new BugType(CheckNames[CK_NewDeleteChecker],
1998 auto R = llvm::make_unique<BugReport>(
1999 *BT_DoubleDelete,
"Attempt to delete released memory", N);
2001 R->markInteresting(Sym);
2002 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2011 if (!ChecksEnabled[CK_MallocChecker] &&
2012 !ChecksEnabled[CK_NewDeleteChecker])
2017 if (!CheckKind.hasValue())
2021 if (!BT_UseZerroAllocated[*CheckKind])
2022 BT_UseZerroAllocated[*CheckKind].reset(
2023 new BugType(CheckNames[*CheckKind],
"Use of zero allocated",
2026 auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
2027 "Use of zero-allocated memory", N);
2031 R->markInteresting(Sym);
2032 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2040 const Expr *FreeExpr)
const {
2041 if (!ChecksEnabled[CK_MallocChecker])
2045 if (!CheckKind.hasValue())
2049 if (!BT_BadFree[*CheckKind])
2050 BT_BadFree[*CheckKind].reset(
2051 new BugType(CheckNames[*CheckKind],
"Bad free",
"Memory Error"));
2054 llvm::raw_svector_ostream Os(Buf);
2057 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2058 MR = ER->getSuperRegion();
2060 Os <<
"Argument to ";
2061 if (!printAllocDeallocName(Os, C, FreeExpr))
2062 Os <<
"deallocator";
2064 Os <<
" is a function pointer";
2066 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str(), N);
2067 R->markInteresting(MR);
2077 bool SuffixWithN)
const {
2088 SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
2096 svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
2102 SVal TotalSize = State->getSVal(Arg1, LCtx);
2104 TotalSize = evalMulForBufferSize(C, Arg1, CE->
getArg(2));
2111 svalBuilder.makeIntValWithPtrWidth(0,
false));
2114 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
2116 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
2119 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
2120 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
2124 if (PrtIsNull && !SizeIsZero) {
2130 if (PrtIsNull && SizeIsZero)
2136 SVal RetVal = State->getSVal(CE, LCtx);
2138 if (!FromPtr || !ToPtr)
2141 bool ReleasedAllocated =
false;
2146 false, ReleasedAllocated)){
2156 FreeMemAux(C, CE, State, 0,
false, ReleasedAllocated)) {
2165 Kind = RPIsFreeOnFailure;
2166 else if (!ReleasedAllocated)
2167 Kind = RPDoNotTrackAfterFailure;
2171 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
2172 ReallocPair(FromPtr, Kind));
2175 return stateRealloc;
2192 return MallocMemAux(C, CE, TotalSize, zeroVal, State);
2202 const MemRegion *ReferenceRegion =
nullptr;
2206 if (!State->get<RegionState>(Sym))
2211 if (!ReferenceRegion) {
2213 SVal Val = State->getSVal(MR);
2220 ReferenceRegion = MR;
2228 if (NContext == LeakContext ||
2234 return LeakInfo(AllocNode, ReferenceRegion);
2240 if (!ChecksEnabled[CK_MallocChecker] &&
2241 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2244 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2245 assert(RS &&
"cannot leak an untracked symbol");
2248 if (Family == AF_Alloca)
2252 CheckKind = getCheckIfTracked(Family,
true);
2254 if (!CheckKind.hasValue())
2258 if (!BT_Leak[*CheckKind]) {
2259 BT_Leak[*CheckKind].reset(
new BugType(CheckNames[*CheckKind],
"Memory leak",
2266 BT_Leak[*CheckKind]->setSuppressOnSink(
true);
2275 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2284 llvm::raw_svector_ostream os(buf);
2286 os <<
"Potential leak of memory pointed to by ";
2289 os <<
"Potential memory leak";
2292 auto R = llvm::make_unique<BugReport>(
2293 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2295 R->markInteresting(Sym);
2296 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym,
true));
2300 void MallocChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
2307 RegionStateTy RS = state->get<RegionState>();
2308 RegionStateTy::Factory &F = state->get_context<RegionState>();
2311 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2312 if (SymReaper.
isDead(I->first)) {
2313 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2314 Errors.push_back(I->first);
2316 RS = F.remove(RS, I->first);
2322 ReallocPairsTy RP = state->get<ReallocPairs>();
2323 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2324 if (SymReaper.
isDead(I->first) ||
2325 SymReaper.
isDead(I->second.ReallocatedSym)) {
2326 state = state->remove<ReallocPairs>(I->first);
2331 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2332 for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
2333 if (SymReaper.
isDead(I->first) ||
2334 SymReaper.
isDead(I->second)) {
2335 state = state->remove<FreeReturnValue>(I->first);
2341 if (!Errors.empty()) {
2346 I = Errors.begin(), E = Errors.end(); I != E; ++I) {
2347 reportLeak(*I, N, C);
2355 void MallocChecker::checkPreCall(
const CallEvent &Call,
2359 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2360 if (!Sym || checkDoubleDelete(Sym, C))
2371 if (ChecksEnabled[CK_MallocChecker] &&
2372 (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
2373 isCMemFunction(FD, Ctx, AF_IfNameIndex,
2374 MemoryOperationKind::MOK_Free)))
2377 if (ChecksEnabled[CK_NewDeleteChecker] &&
2378 isStandardNewDelete(FD, Ctx))
2384 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2385 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2390 for (
unsigned I = 0, E = Call.
getNumArgs(); I != E; ++I) {
2396 if (checkUseAfterFree(Sym, C, Call.
getArgExpr(I)))
2416 if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
2419 Sym = BMR->getSymbol();
2423 checkUseAfterFree(Sym, C, E);
2429 void MallocChecker::checkPostStmt(
const BlockExpr *BE,
2439 cast<BlockDataRegion>(state->getSVal(BE,
2452 for ( ; I != E; ++I) {
2453 const VarRegion *VR = I.getCapturedRegion();
2457 Regions.push_back(VR);
2461 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2462 Regions.data() + Regions.size()).getState();
2468 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2469 return (RS && RS->isReleased());
2473 const Stmt *S)
const {
2475 if (isReleased(Sym, C)) {
2484 const Stmt *S)
const {
2487 if (
const RefState *RS = C.
getState()->get<RegionState>(Sym)) {
2488 if (RS->isAllocatedOfSizeZero())
2489 ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
2491 else if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
2498 if (isReleased(Sym, C)) {
2499 ReportDoubleDelete(C, Sym);
2506 void MallocChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
2510 checkUseAfterFree(Sym, C, S);
2511 checkUseZeroAllocated(Sym, C, S);
2519 bool Assumption)
const {
2520 RegionStateTy RS = state->get<RegionState>();
2521 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2526 state = state->remove<RegionState>(I.getKey());
2531 ReallocPairsTy RP = state->get<ReallocPairs>();
2532 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2539 SymbolRef ReallocSym = I.getData().ReallocatedSym;
2540 if (
const RefState *RS = state->get<RegionState>(ReallocSym)) {
2541 if (RS->isReleased()) {
2542 if (I.getData().Kind == RPToBeFreedAfterFailure)
2543 state = state->set<RegionState>(ReallocSym,
2544 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
2545 else if (I.getData().Kind == RPDoNotTrackAfterFailure)
2546 state = state->remove<RegionState>(ReallocSym);
2548 assert(I.getData().Kind == RPIsFreeOnFailure);
2551 state = state->remove<ReallocPairs>(I.getKey());
2557 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
2562 EscapingSymbol =
nullptr;
2568 if (!(isa<SimpleFunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
2572 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
2588 return *FreeWhenDone;
2594 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
2595 if (FirstSlot.endswith(
"NoCopy"))
2602 if (FirstSlot.startswith(
"addPointer") ||
2603 FirstSlot.startswith(
"insertPointer") ||
2604 FirstSlot.startswith(
"replacePointer") ||
2605 FirstSlot.equals(
"valueWithPointer")) {
2612 if (Msg->getMethodFamily() ==
OMF_init) {
2613 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
2623 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
2627 ASTContext &ASTC = State->getStateManager().getContext();
2631 if (isMemFunction(FD, ASTC))
2642 StringRef FName = II->
getName();
2646 if (FName.endswith(
"NoCopy")) {
2650 for (
unsigned i = 1; i < Call->
getNumArgs(); ++i) {
2652 if (
const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
2653 StringRef DeallocatorName = DE->getFoundDecl()->getName();
2654 if (DeallocatorName ==
"kCFAllocatorNull")
2665 if (FName ==
"funopen")
2672 if (FName ==
"setbuf" || FName ==
"setbuffer" ||
2673 FName ==
"setlinebuf" || FName ==
"setvbuf") {
2676 if (
const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
2677 if (
const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
2678 if (D->getCanonicalDecl()->getName().find(
"std") != StringRef::npos)
2688 if (FName ==
"CGBitmapContextCreate" ||
2689 FName ==
"CGBitmapContextCreateWithData" ||
2690 FName ==
"CVPixelBufferCreateWithBytes" ||
2691 FName ==
"CVPixelBufferCreateWithPlanarBytes" ||
2692 FName ==
"OSAtomicEnqueue") {
2696 if (FName ==
"postEvent" &&
2701 if (FName ==
"postEvent" &&
2706 if (FName ==
"connectImpl" &&
2728 return (RS->getAllocationFamily() == AF_CXXNewArray ||
2729 RS->getAllocationFamily() == AF_CXXNew);
2736 return checkPointerEscapeAux(State, Escaped, Call, Kind, &
retTrue);
2743 return checkPointerEscapeAux(State, Escaped, Call, Kind,
2751 bool(*CheckRefState)(
const RefState*))
const {
2756 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
2762 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2767 if (EscapingSymbol && EscapingSymbol != sym)
2770 if (
const RefState *RS = State->get<RegionState>(sym)) {
2771 if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
2772 CheckRefState(RS)) {
2773 State = State->remove<RegionState>(sym);
2774 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2783 ReallocPairsTy currMap = currState->get<ReallocPairs>();
2784 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2786 for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end();
2789 if (!currMap.lookup(sym))
2796 std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
2802 const RefState *RS = state->get<RegionState>(Sym);
2803 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2815 const char *Msg =
nullptr;
2817 if (Mode == Normal) {
2818 if (isAllocated(RS, RSPrev, S)) {
2819 Msg =
"Memory is allocated";
2821 "Returned allocated memory");
2822 }
else if (isReleased(RS, RSPrev, S)) {
2823 Msg =
"Memory is released";
2825 "Returning; memory was released");
2826 }
else if (isRelinquished(RS, RSPrev, S)) {
2827 Msg =
"Memory ownership is transferred";
2829 }
else if (isReallocFailedCheck(RS, RSPrev, S)) {
2830 Mode = ReallocationFailed;
2831 Msg =
"Reallocation failed";
2832 StackHint =
new StackHintGeneratorForReallocationFailed(Sym,
2833 "Reallocation failed");
2837 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
2838 "We only support one failed realloc at a time.");
2840 FailedReallocSymbol = sym;
2845 }
else if (Mode == ReallocationFailed) {
2846 assert(FailedReallocSymbol &&
"No symbol to look for.");
2849 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
2851 Msg =
"Attempt to reallocate memory";
2853 "Returned reallocated memory");
2854 FailedReallocSymbol =
nullptr;
2866 return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg,
true, StackHint);
2869 void MallocChecker::printState(raw_ostream &Out,
ProgramStateRef State,
2870 const char *NL,
const char *Sep)
const {
2872 RegionStateTy RS = State->get<RegionState>();
2874 if (!RS.isEmpty()) {
2875 Out << Sep <<
"MallocChecker :" << NL;
2876 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2877 const RefState *RefS = State->get<RegionState>(I.getKey());
2880 if (!CheckKind.hasValue())
2881 CheckKind = getCheckIfTracked(Family,
true);
2883 I.getKey()->dumpToStream(Out);
2885 I.getData().dump(Out);
2886 if (CheckKind.hasValue())
2887 Out <<
" (" << CheckNames[*CheckKind].getName() <<
")";
2897 "Optimistic",
false, checker);
2898 checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] =
true;
2899 checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
2903 if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
2904 checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] =
true;
2907 checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
2912 #define REGISTER_CHECKER(name) \ 2913 void ento::register##name(CheckerManager &mgr) { \ 2914 registerCStringCheckerBasic(mgr); \ 2915 MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \ 2916 checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \ 2917 "Optimistic", false, checker); \ 2918 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \ 2919 checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
const BlockDecl * getBlockDecl() const
An instance of this class is created to represent a function declaration or definition.
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Smart pointer class that efficiently represents Objective-C method names.
QualType getArrayIndexType() const
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.
const char *const MemoryError
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool hasCaptures() const
hasCaptures - True if this block (or its nested blocks) captures anything of local storage from its e...
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
bool operator==(CanQual< T > x, CanQual< U > y)
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
A helper class which wraps a boolean value set to false by default.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Defines the SourceManager interface.
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)
StringRef getDescription() const
FunctionDecl * getOperatorNew() const
Constructs a Stack hint for the given symbol.
Represents a call to a C++ constructor.
const TargetInfo & getTargetInfo() const
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
const ProgramStateRef & getState() const
Represents a C++ constructor within a class.
Value representing integer constant.
bool isConsumedExpr(Expr *E) const
VarDecl - An instance of this class is created to represent a variable declaration or definition...
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
NonLoc makeArrayIndex(uint64_t idx)
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
unsigned getNumPlacementArgs() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
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.
bool isParentOf(const LocationContext *LC) const
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
const MemRegion * getSuperRegion() 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...
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call)
One of these records is kept for each identifier that is lexed.
MemRegionManager & getRegionManager()
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
const Expr * getRetValue() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
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
virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const
getExtent - Returns the size of the region in bytes.
ArrayRef< ParmVarDecl * > parameters() 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.
FunctionDecl * getOperatorDelete() const
CharUnits - This is an opaque type for sizes expressed in character units.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
const StackFrameContext * getCurrentStackFrame() const
const LocationContext * getLocationContext() const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
referenced_vars_iterator referenced_vars_end() const
Represent a region's offset within the top level base region.
const MemSpaceRegion * getMemorySpace() const
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()
virtual QualType getType() const =0
CheckName getCurrentCheckName() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
Const iterator for iterating over Stmt * arrays that contain only Expr *.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any...
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
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.
bool hasDeadSymbols() const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
const RegionTy * getAs() const
SymbolicRegion - A special, "non-concrete" region.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
Expr - This represents one expression.
bool isVariadic() const
Whether this function is variadic.
const FunctionProtoType * T
const IdentifierInfo * getBaseTypeIdentifier() const
Retrieves a pointer to the name of the base type.
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.
The pointer has been passed to a function call directly.
Represents a call to any sort of function that might have a FunctionDecl.
bool isInSystemHeader() const
Returns true if the callee is known to be from a system header.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
SymbolManager & getSymbolManager()
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
unsigned getNumArgs() const
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
ParentMap & getParentMap() const
const VarDecl * getDecl() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
virtual bool argumentsMayEscape() const
Returns true if any of the arguments are known to escape to long- term storage, even if this method w...
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
const MemRegion * StripCasts(bool StripBaseCasts=true) 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.
SymbolRef getSymbol() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
const MemRegion * getAsRegion() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
ASTContext & getContext()
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
QualType getAllocatedType() const
const ParmVarDecl * getParamDecl(unsigned i) const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
const StackFrameContext * getStackFrame() const
A class responsible for cleaning up unused symbols.
static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState)
referenced_vars_iterator referenced_vars_begin() const
DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, const LocationContext *LCtx, unsigned Count)
Conjure a symbol representing heap allocated memory region.
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
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.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
Selector getSelector() const
Dataflow Directional Tag Classes.
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...
Represents an abstract call to a function or method along a particular path.
AnalyzerOptions & getAnalyzerOptions()
const Decl * getDecl() const
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SubRegion - A region that subsets another larger region.
#define REGISTER_CHECKER(name)
const ProgramStateRef & getState() const
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword...
uint64_t getCharWidth() const
Return the size of the character type, in bits.
static Optional< bool > getFreeWhenDoneArg(const ObjCMethodCall &Call)
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
int64_t getOffset() const
arg_iterator placement_arg_begin()
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
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.
const MemRegion * getBaseRegion() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SValBuilder & getSValBuilder()
Defines the clang::TargetInfo interface.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
ElementRegin is used to represent both array elements and casts.
std::string getQualifiedNameAsString() const
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...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
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 isFunctionPointerType() const
const LocationContext * getLocationContext() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
SourceManager & getSourceManager()
bool hasSymbolicOffset() const
bool isUnknownOrUndef() const
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.