30 #include "llvm/ADT/STLExtras.h" 31 #include "llvm/ADT/SmallString.h" 32 #include "llvm/ADT/StringExtras.h" 37 using namespace clang;
74 RefState(
Kind k,
const Stmt *s,
unsigned family)
75 : S(s), K(k), Family(family) {
76 assert(family != AF_None);
79 bool isAllocated()
const {
return K == Allocated; }
80 bool isAllocatedOfSizeZero()
const {
return K == AllocatedOfSizeZero; }
81 bool isReleased()
const {
return K == Released; }
82 bool isRelinquished()
const {
return K == Relinquished; }
83 bool isEscaped()
const {
return K == Escaped; }
87 const Stmt *getStmt()
const {
return S; }
90 return K == X.K && S == X.S && Family == X.Family;
93 static RefState getAllocated(
unsigned family,
const Stmt *s) {
94 return RefState(Allocated, s, family);
96 static RefState getAllocatedOfSizeZero(
const RefState *RS) {
97 return RefState(AllocatedOfSizeZero, RS->getStmt(),
98 RS->getAllocationFamily());
100 static RefState getReleased(
unsigned family,
const Stmt *s) {
101 return RefState(Released, s, family);
103 static RefState getRelinquished(
unsigned family,
const Stmt *s) {
104 return RefState(Relinquished, s, family);
106 static RefState getEscaped(
const RefState *RS) {
107 return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
110 void Profile(llvm::FoldingSetNodeID &
ID)
const {
113 ID.AddInteger(Family);
116 void dump(raw_ostream &OS)
const {
117 switch (static_cast<Kind>(K)) {
118 #define CASE(ID) case ID: OS << #ID; break; 120 CASE(AllocatedOfSizeZero)
127 LLVM_DUMP_METHOD
void dump()
const {
dump(llvm::errs()); }
131 RPToBeFreedAfterFailure,
135 RPDoNotTrackAfterFailure
147 ReallocatedSym(S),
Kind(K) {}
148 void Profile(llvm::FoldingSetNodeID &
ID)
const {
150 ID.AddPointer(ReallocatedSym);
153 return ReallocatedSym == X.ReallocatedSym &&
158 typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo;
160 class MallocChecker :
public Checker<check::DeadSymbols,
161 check::PointerEscape,
162 check::ConstPointerEscape,
163 check::PreStmt<ReturnStmt>,
165 check::PostStmt<CallExpr>,
166 check::PostStmt<CXXNewExpr>,
168 check::PreStmt<CXXDeleteExpr>,
169 check::PostStmt<BlockExpr>,
170 check::PostObjCMessage,
176 : II_alloca(
nullptr), II_win_alloca(
nullptr), II_malloc(
nullptr),
177 II_free(
nullptr), II_realloc(
nullptr), II_calloc(
nullptr),
178 II_valloc(
nullptr), II_reallocf(
nullptr), II_strndup(
nullptr),
179 II_strdup(
nullptr), II_win_strdup(
nullptr), II_kmalloc(
nullptr),
180 II_if_nameindex(
nullptr), II_if_freenameindex(
nullptr),
181 II_wcsdup(
nullptr), II_win_wcsdup(
nullptr), II_g_malloc(
nullptr),
182 II_g_malloc0(
nullptr), II_g_realloc(
nullptr), II_g_try_malloc(
nullptr),
183 II_g_try_malloc0(
nullptr), II_g_try_realloc(
nullptr),
184 II_g_free(
nullptr), II_g_memdup(
nullptr), II_g_malloc_n(
nullptr),
185 II_g_malloc0_n(
nullptr), II_g_realloc_n(
nullptr),
186 II_g_try_malloc_n(
nullptr), II_g_try_malloc0_n(
nullptr),
187 II_g_try_realloc_n(
nullptr) {}
194 CK_NewDeleteLeaksChecker,
195 CK_MismatchedDeallocatorChecker,
199 enum class MemoryOperationKind {
221 bool Assumption)
const;
222 void checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
235 const char *NL,
const char *Sep)
const override;
238 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
239 mutable std::unique_ptr<BugType> BT_DoubleDelete;
240 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
241 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
242 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
243 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
244 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
245 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
246 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
247 mutable IdentifierInfo *II_alloca, *II_win_alloca, *II_malloc, *II_free,
248 *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
249 *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
250 *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
251 *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,
252 *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,
253 *II_g_try_realloc, *II_g_free, *II_g_memdup,
254 *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,
255 *II_g_try_malloc_n, *II_g_try_malloc0_n,
268 const Expr *E)
const;
273 const Expr *DeallocExpr)
const;
276 void printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family)
const;
285 MemoryOperationKind MemKind)
const;
298 const unsigned AllocationSizeArg,
304 const OwnershipAttr* Att,
333 const OwnershipAttr* Att,
338 bool &ReleasedAllocated,
339 bool ReturnsNullOnFailure =
false)
const;
341 const Expr *ParentExpr,
344 bool &ReleasedAllocated,
345 bool ReturnsNullOnFailure =
false)
const;
348 bool FreesMemOnFailure,
350 bool SuffixWithN =
false)
const;
352 const Expr *BlockBytes);
362 const Stmt *S)
const;
376 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
const CallEvent *Call,
385 bool(*CheckRefState)(
const RefState*))
const;
392 bool IsALeakCheck =
false)
const;
394 const Stmt *AllocDeallocStmt,
395 bool IsALeakCheck =
false)
const;
397 bool IsALeakCheck =
false)
const;
399 static bool SummarizeValue(raw_ostream &os,
SVal V);
400 static bool SummarizeRegion(raw_ostream &os,
const MemRegion *MR);
402 const Expr *DeallocExpr)
const;
406 const Expr *DeallocExpr,
const RefState *RS,
407 SymbolRef Sym,
bool OwnershipTransferred)
const;
409 const Expr *DeallocExpr,
410 const Expr *AllocExpr =
nullptr)
const;
436 enum NotificationMode {
445 NotificationMode Mode;
457 MallocBugVisitor(
SymbolRef S,
bool isLeak =
false)
458 : Sym(S), Mode(Normal), FailedReallocSymbol(
nullptr),
459 ReleaseDestructorLC(
nullptr), IsLeak(isLeak) {}
461 static void *getTag() {
466 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
467 ID.AddPointer(getTag());
471 inline bool isAllocated(
const RefState *S,
const RefState *SPrev,
474 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
475 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
476 (!SPrev || !(SPrev->isAllocated() ||
477 SPrev->isAllocatedOfSizeZero())));
480 inline bool isReleased(
const RefState *S,
const RefState *SPrev,
484 bool IsReleased = (S && S->isReleased()) &&
485 (!SPrev || !SPrev->isReleased());
486 assert(!IsReleased ||
487 (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt))) ||
488 (!Stmt && S->getAllocationFamily() == AF_InnerBuffer));
492 inline bool isRelinquished(
const RefState *S,
const RefState *SPrev,
495 return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
496 isa<ObjCPropertyRefExpr>(Stmt)) &&
497 (S && S->isRelinquished()) &&
498 (!SPrev || !SPrev->isRelinquished()));
501 inline bool isReallocFailedCheck(
const RefState *S,
const RefState *SPrev,
507 return ((!Stmt || !isa<CallExpr>(Stmt)) &&
508 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
509 (SPrev && !(SPrev->isAllocated() ||
510 SPrev->isAllocatedOfSizeZero())));
513 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
518 std::shared_ptr<PathDiagnosticPiece>
528 return std::make_shared<PathDiagnosticEventPiece>(L, BR.
getDescription(),
533 class StackHintGeneratorForReallocationFailed
536 StackHintGeneratorForReallocationFailed(
SymbolRef S, StringRef M)
539 std::string getMessageForArg(
const Expr *ArgE,
540 unsigned ArgIndex)
override {
545 llvm::raw_svector_ostream os(buf);
547 os <<
"Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
548 <<
" parameter failed";
554 return "Reallocation of returned value failed";
576 bool VisitSymbol(
SymbolRef sym)
override {
577 state = state->remove<RegionState>(sym);
583 void MallocChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
590 II_reallocf = &Ctx.
Idents.
get(
"reallocf");
597 II_if_nameindex = &Ctx.
Idents.
get(
"if_nameindex");
598 II_if_freenameindex = &Ctx.
Idents.
get(
"if_freenameindex");
601 II_win_strdup = &Ctx.
Idents.
get(
"_strdup");
602 II_win_wcsdup = &Ctx.
Idents.
get(
"_wcsdup");
603 II_win_alloca = &Ctx.
Idents.
get(
"_alloca");
606 II_g_malloc = &Ctx.
Idents.
get(
"g_malloc");
607 II_g_malloc0 = &Ctx.
Idents.
get(
"g_malloc0");
608 II_g_realloc = &Ctx.
Idents.
get(
"g_realloc");
609 II_g_try_malloc = &Ctx.
Idents.
get(
"g_try_malloc");
610 II_g_try_malloc0 = &Ctx.
Idents.
get(
"g_try_malloc0");
611 II_g_try_realloc = &Ctx.
Idents.
get(
"g_try_realloc");
613 II_g_memdup = &Ctx.
Idents.
get(
"g_memdup");
614 II_g_malloc_n = &Ctx.
Idents.
get(
"g_malloc_n");
615 II_g_malloc0_n = &Ctx.
Idents.
get(
"g_malloc0_n");
616 II_g_realloc_n = &Ctx.
Idents.
get(
"g_realloc_n");
617 II_g_try_malloc_n = &Ctx.
Idents.
get(
"g_try_malloc_n");
618 II_g_try_malloc0_n = &Ctx.
Idents.
get(
"g_try_malloc0_n");
619 II_g_try_realloc_n = &Ctx.
Idents.
get(
"g_try_realloc_n");
623 if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any))
626 if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
629 if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
632 if (isStandardNewDelete(FD, C))
638 bool MallocChecker::isCMemFunction(
const FunctionDecl *FD,
641 MemoryOperationKind MemKind)
const {
645 bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any ||
646 MemKind == MemoryOperationKind::MOK_Free);
647 bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any ||
648 MemKind == MemoryOperationKind::MOK_Allocate);
652 initIdentifierInfo(C);
654 if (Family == AF_Malloc && CheckFree) {
655 if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
660 if (Family == AF_Malloc && CheckAlloc) {
661 if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
662 FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
663 FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
664 FunI == II_win_wcsdup || FunI == II_kmalloc ||
665 FunI == II_g_malloc || FunI == II_g_malloc0 ||
666 FunI == II_g_realloc || FunI == II_g_try_malloc ||
667 FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||
668 FunI == II_g_memdup || FunI == II_g_malloc_n ||
669 FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||
670 FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||
671 FunI == II_g_try_realloc_n)
675 if (Family == AF_IfNameIndex && CheckFree) {
676 if (FunI == II_if_freenameindex)
680 if (Family == AF_IfNameIndex && CheckAlloc) {
681 if (FunI == II_if_nameindex)
685 if (Family == AF_Alloca && CheckAlloc) {
686 if (FunI == II_alloca || FunI == II_win_alloca)
691 if (Family != AF_Malloc)
694 if (IsOptimistic && FD->
hasAttrs()) {
696 OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
697 if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
700 }
else if (OwnKind == OwnershipAttr::Returns) {
714 bool MallocChecker::isStandardNewDelete(
const FunctionDecl *FD,
720 if (Kind != OO_New && Kind != OO_Array_New &&
721 Kind != OO_Delete && Kind != OO_Array_Delete)
725 if (isa<CXXMethodDecl>(FD))
732 return II->getName().equals(
"nothrow_t");
764 if (!KernelZeroFlagVal.hasValue()) {
765 if (OS == llvm::Triple::FreeBSD)
766 KernelZeroFlagVal = 0x0100;
767 else if (OS == llvm::Triple::NetBSD)
768 KernelZeroFlagVal = 0x0002;
769 else if (OS == llvm::Triple::OpenBSD)
770 KernelZeroFlagVal = 0x0008;
771 else if (OS == llvm::Triple::Linux)
773 KernelZeroFlagVal = 0x8000;
810 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
813 if (TrueState && !FalseState) {
815 return MallocMemAux(C, CE, CE->
getArg(0), ZeroVal, TrueState);
822 const Expr *BlockBytes) {
827 SVal TotalSize = SB.
evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,
841 bool ReleasedAllocatedMemory =
false;
847 if (FunI == II_malloc || FunI == II_g_malloc || FunI == II_g_try_malloc) {
853 State = ProcessZeroAllocation(C, CE, 0, State);
856 performKernelMalloc(CE, C, State);
857 if (MaybeState.hasValue())
858 State = MaybeState.getValue();
862 }
else if (FunI == II_kmalloc) {
866 performKernelMalloc(CE, C, State);
867 if (MaybeState.hasValue())
868 State = MaybeState.getValue();
871 }
else if (FunI == II_valloc) {
875 State = ProcessZeroAllocation(C, CE, 0, State);
876 }
else if (FunI == II_realloc || FunI == II_g_realloc ||
877 FunI == II_g_try_realloc) {
878 State = ReallocMemAux(C, CE,
false, State);
879 State = ProcessZeroAllocation(C, CE, 1, State);
880 }
else if (FunI == II_reallocf) {
881 State = ReallocMemAux(C, CE,
true, State);
882 State = ProcessZeroAllocation(C, CE, 1, State);
883 }
else if (FunI == II_calloc) {
884 State = CallocMem(C, CE, State);
885 State = ProcessZeroAllocation(C, CE, 0, State);
886 State = ProcessZeroAllocation(C, CE, 1, State);
887 }
else if (FunI == II_free || FunI == II_g_free) {
888 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
889 }
else if (FunI == II_strdup || FunI == II_win_strdup ||
890 FunI == II_wcsdup || FunI == II_win_wcsdup) {
891 State = MallocUpdateRefState(C, CE, State);
892 }
else if (FunI == II_strndup) {
893 State = MallocUpdateRefState(C, CE, State);
894 }
else if (FunI == II_alloca || FunI == II_win_alloca) {
899 State = ProcessZeroAllocation(C, CE, 0, State);
909 State = ProcessZeroAllocation(C, CE, 0, State);
911 else if (K == OO_Array_New) {
914 State = ProcessZeroAllocation(C, CE, 0, State);
916 else if (K == OO_Delete || K == OO_Array_Delete)
917 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
919 llvm_unreachable(
"not a new/delete operator");
920 }
else if (FunI == II_if_nameindex) {
925 }
else if (FunI == II_if_freenameindex) {
926 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
927 }
else if (FunI == II_g_malloc0 || FunI == II_g_try_malloc0) {
932 State = MallocMemAux(C, CE, CE->
getArg(0), zeroVal,
State);
933 State = ProcessZeroAllocation(C, CE, 0, State);
934 }
else if (FunI == II_g_memdup) {
938 State = ProcessZeroAllocation(C, CE, 1, State);
939 }
else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||
940 FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
944 if (FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
949 State = MallocMemAux(C, CE, TotalSize, Init, State);
950 State = ProcessZeroAllocation(C, CE, 0, State);
951 State = ProcessZeroAllocation(C, CE, 1, State);
952 }
else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n) {
955 State = ReallocMemAux(C, CE,
false, State,
true);
956 State = ProcessZeroAllocation(C, CE, 1, State);
957 State = ProcessZeroAllocation(C, CE, 2, State);
961 if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
966 switch (I->getOwnKind()) {
967 case OwnershipAttr::Returns:
968 State = MallocMemReturnsAttr(C, CE, I, State);
970 case OwnershipAttr::Takes:
971 case OwnershipAttr::Holds:
972 State = FreeMemAttr(C, CE, I, State);
990 const Expr *Arg =
nullptr;
992 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
993 Arg = CE->
getArg(AllocationSizeArg);
995 else if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
997 Arg = NE->getArraySize();
1002 llvm_unreachable(
"not a CallExpr or CXXNewExpr");
1017 std::tie(TrueState, FalseState) =
1018 State->assume(SvalBuilder.
evalEQ(State, *DefArgVal, Zero));
1020 if (TrueState && !FalseState) {
1021 SymbolRef Sym = RetVal->getAsLocSymbol();
1025 const RefState *RS = State->get<RegionState>(Sym);
1027 if (RS->isAllocated())
1028 return TrueState->set<RegionState>(Sym,
1029 RefState::getAllocatedOfSizeZero(RS));
1037 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
1048 while (!PointeeType.isNull()) {
1049 Result = PointeeType;
1067 for (
const auto *CtorParam : CtorD->
parameters()) {
1070 if (CtorParamPointeeT.
isNull())
1082 void MallocChecker::processNewAllocation(
const CXXNewExpr *NE,
1089 checkUseAfterFree(Sym, C, *I);
1103 State = MallocUpdateRefState(C, NE, State, NE->
isArray() ? AF_CXXNewArray
1105 State = addExtentSize(C, NE, State, Target);
1106 State = ProcessZeroAllocation(C, NE, 0, State, Target);
1110 void MallocChecker::checkPostStmt(
const CXXNewExpr *NE,
1113 processNewAllocation(NE, C, C.
getSVal(NE));
1116 void MallocChecker::checkNewAllocator(
const CXXNewExpr *NE,
SVal Target,
1119 processNewAllocation(NE, C, Target);
1136 ElementCount = C.
getSVal(SizeExpr);
1144 ElementCount = svalBuilder.
makeIntVal(1,
true);
1163 State = State->assume(extentMatchesSize,
true);
1171 if (!ChecksEnabled[CK_NewDeleteChecker])
1179 bool ReleasedAllocated;
1181 false, ReleasedAllocated);
1193 return FirstSlot ==
"dataWithBytesNoCopy" ||
1194 FirstSlot ==
"initWithBytesNoCopy" ||
1195 FirstSlot ==
"initWithCharactersNoCopy";
1202 for (
unsigned i = 1; i < S.
getNumArgs(); ++i)
1204 return !Call.getArgSVal(i).isZeroConstant();
1209 void MallocChecker::checkPostObjCMessage(
const ObjCMethodCall &Call,
1221 bool ReleasedAllocatedMemory;
1224 true, ReleasedAllocatedMemory,
1232 const OwnershipAttr *Att,
1237 if (Att->getModule() != II_malloc)
1240 OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
1256 return MallocMemAux(C, CE, C.
getSVal(SizeEx), Init,
State, Family);
1282 State = State->bindDefaultInitial(RetVal, Init, LCtx);
1286 dyn_cast_or_null<SymbolicRegion>(RetVal.
getAsRegion());
1294 svalBuilder.
evalEQ(State, Extent, *DefinedSize);
1296 State = State->assume(extentMatchesSize,
true);
1300 return MallocUpdateRefState(C, CE, State, Family);
1316 if (!RetVal->getAs<
Loc>())
1319 SymbolRef Sym = RetVal->getAsLocSymbol();
1325 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1330 const OwnershipAttr *Att,
1335 if (Att->getModule() != II_malloc)
1338 bool ReleasedAllocated =
false;
1340 for (
const auto &Arg : Att->args()) {
1342 C, CE, State, Arg.getASTIndex(),
1343 Att->getOwnKind() == OwnershipAttr::Holds, ReleasedAllocated);
1355 bool &ReleasedAllocated,
1356 bool ReturnsNullOnFailure)
const {
1363 return FreeMemAux(C, CE->
getArg(Num), CE,
State, Hold,
1364 ReleasedAllocated, ReturnsNullOnFailure);
1371 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1373 assert(*Ret &&
"We should not store the null return symbol");
1376 RetStatusSymbol = *Ret;
1383 const Stmt *S)
const {
1387 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1395 if (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Any))
1398 if (isStandardNewDelete(FD, Ctx)) {
1400 if (Kind == OO_New || Kind == OO_Delete)
1402 else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
1403 return AF_CXXNewArray;
1406 if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
1407 return AF_IfNameIndex;
1409 if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
1415 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
1416 return NE->
isArray() ? AF_CXXNewArray : AF_CXXNew;
1419 return DE->
isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
1421 if (isa<ObjCMessageExpr>(S))
1427 bool MallocChecker::printAllocDeallocName(raw_ostream &os,
CheckerContext &C,
1428 const Expr *E)
const {
1429 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1436 if (!FD->isOverloadedOperator())
1442 if (Msg->isInstanceMessage())
1446 Msg->getSelector().
print(os);
1450 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1467 void MallocChecker::printExpectedAllocName(raw_ostream &os,
CheckerContext &C,
1468 const Expr *E)
const {
1472 case AF_Malloc: os <<
"malloc()";
return;
1473 case AF_CXXNew: os <<
"'new'";
return;
1474 case AF_CXXNewArray: os <<
"'new[]'";
return;
1475 case AF_IfNameIndex: os <<
"'if_nameindex()'";
return;
1476 case AF_InnerBuffer: os <<
"container-specific allocator";
return;
1478 case AF_None: llvm_unreachable(
"not a deallocation expression");
1482 void MallocChecker::printExpectedDeallocName(raw_ostream &os,
1485 case AF_Malloc: os <<
"free()";
return;
1486 case AF_CXXNew: os <<
"'delete'";
return;
1487 case AF_CXXNewArray: os <<
"'delete[]'";
return;
1488 case AF_IfNameIndex: os <<
"'if_freenameindex()'";
return;
1489 case AF_InnerBuffer: os <<
"container-specific deallocator";
return;
1491 case AF_None: llvm_unreachable(
"suspicious argument");
1496 const Expr *ArgExpr,
1497 const Expr *ParentExpr,
1500 bool &ReleasedAllocated,
1501 bool ReturnsNullOnFailure)
const {
1517 std::tie(notNullState, nullState) = State->assume(location);
1518 if (nullState && !notNullState)
1538 if (isa<BlockDataRegion>(R)) {
1547 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1556 if (isa<AllocaRegion>(R))
1571 const RefState *RsBase = State->get<RegionState>(SymBase);
1572 SymbolRef PreviousRetStatusSymbol =
nullptr;
1577 if (RsBase->getAllocationFamily() == AF_Alloca) {
1583 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1585 ReportDoubleFree(C, ParentExpr->
getSourceRange(), RsBase->isReleased(),
1586 SymBase, PreviousRetStatusSymbol);
1591 }
else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
1592 RsBase->isEscaped()) {
1595 bool DeallocMatchesAlloc =
1596 RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1597 if (!DeallocMatchesAlloc) {
1599 ParentExpr, RsBase, SymBase, Hold);
1609 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1610 ReportOffsetFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr,
1618 ReportFunctionPointerFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr);
1622 ReleasedAllocated = (RsBase !=
nullptr) && (RsBase->isAllocated() ||
1623 RsBase->isAllocatedOfSizeZero());
1626 State = State->remove<FreeReturnValue>(SymBase);
1630 if (ReturnsNullOnFailure) {
1633 if (RetStatusSymbol) {
1635 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1640 : getAllocationFamily(C, ParentExpr);
1643 return State->set<RegionState>(SymBase,
1644 RefState::getRelinquished(Family,
1647 return State->set<RegionState>(SymBase,
1648 RefState::getReleased(Family, ParentExpr));
1653 bool IsALeakCheck)
const {
1657 case AF_IfNameIndex: {
1658 if (ChecksEnabled[CK_MallocChecker])
1659 return CK_MallocChecker;
1664 case AF_CXXNewArray:
1666 case AF_InnerBuffer: {
1668 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
1669 return CK_NewDeleteLeaksChecker;
1672 if (ChecksEnabled[CK_NewDeleteChecker])
1673 return CK_NewDeleteChecker;
1678 llvm_unreachable(
"no family");
1681 llvm_unreachable(
"unhandled family");
1686 const Stmt *AllocDeallocStmt,
1687 bool IsALeakCheck)
const {
1688 return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
1694 bool IsALeakCheck)
const {
1695 if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym))
1696 return CK_MallocChecker;
1698 const RefState *RS = C.
getState()->get<RegionState>(Sym);
1700 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
1703 bool MallocChecker::SummarizeValue(raw_ostream &os,
SVal V) {
1705 os <<
"an integer (" << IntVal->getValue() <<
")";
1707 os <<
"a constant address (" << ConstAddr->getValue() <<
")";
1709 os <<
"the address of the label '" <<
Label->getLabel()->getName() <<
"'";
1716 bool MallocChecker::SummarizeRegion(raw_ostream &os,
1719 case MemRegion::FunctionCodeRegionKind: {
1720 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1722 os <<
"the address of the function '" << *FD <<
'\'';
1724 os <<
"the address of a function";
1727 case MemRegion::BlockCodeRegionKind:
1730 case MemRegion::BlockDataRegionKind:
1737 if (isa<StackLocalsSpaceRegion>(MS)) {
1746 os <<
"the address of the local variable '" << VD->
getName() <<
"'";
1748 os <<
"the address of a local stack variable";
1752 if (isa<StackArgumentsSpaceRegion>(MS)) {
1761 os <<
"the address of the parameter '" << VD->
getName() <<
"'";
1763 os <<
"the address of a parameter";
1767 if (isa<GlobalsSpaceRegion>(MS)) {
1776 if (VD->isStaticLocal())
1777 os <<
"the address of the static variable '" << VD->
getName() <<
"'";
1779 os <<
"the address of the global variable '" << VD->getName() <<
"'";
1781 os <<
"the address of a global variable";
1792 const Expr *DeallocExpr)
const {
1794 if (!ChecksEnabled[CK_MallocChecker] &&
1795 !ChecksEnabled[CK_NewDeleteChecker])
1799 getCheckIfTracked(C, DeallocExpr);
1800 if (!CheckKind.hasValue())
1804 if (!BT_BadFree[*CheckKind])
1805 BT_BadFree[*CheckKind].reset(
new BugType(
1809 llvm::raw_svector_ostream os(buf);
1812 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1813 MR = ER->getSuperRegion();
1815 os <<
"Argument to ";
1816 if (!printAllocDeallocName(os, C, DeallocExpr))
1817 os <<
"deallocator";
1820 bool Summarized = MR ? SummarizeRegion(os, MR)
1821 : SummarizeValue(os, ArgVal);
1823 os <<
", which is not memory allocated by ";
1825 os <<
"not memory allocated by ";
1827 printExpectedAllocName(os, C, DeallocExpr);
1829 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
1830 R->markInteresting(MR);
1841 if (ChecksEnabled[CK_MallocChecker])
1842 CheckKind = CK_MallocChecker;
1843 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
1844 CheckKind = CK_MismatchedDeallocatorChecker;
1849 if (!BT_FreeAlloca[*CheckKind])
1850 BT_FreeAlloca[*CheckKind].reset(
new BugType(
1853 auto R = llvm::make_unique<BugReport>(
1854 *BT_FreeAlloca[*CheckKind],
1855 "Memory allocated by alloca() should not be deallocated", N);
1864 const Expr *DeallocExpr,
1867 bool OwnershipTransferred)
const {
1869 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
1873 if (!BT_MismatchedDealloc)
1874 BT_MismatchedDealloc.reset(
1875 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
1879 llvm::raw_svector_ostream os(buf);
1881 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1883 llvm::raw_svector_ostream AllocOs(AllocBuf);
1885 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1887 if (OwnershipTransferred) {
1888 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1889 os << DeallocOs.str() <<
" cannot";
1893 os <<
" take ownership of memory";
1895 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1896 os <<
" allocated by " << AllocOs.str();
1899 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1900 os <<
" allocated by " << AllocOs.str();
1902 os <<
" should be deallocated by ";
1903 printExpectedDeallocName(os, RS->getAllocationFamily());
1905 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1906 os <<
", not " << DeallocOs.str();
1909 auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
1910 R->markInteresting(Sym);
1912 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1919 const Expr *AllocExpr)
const {
1922 if (!ChecksEnabled[CK_MallocChecker] &&
1923 !ChecksEnabled[CK_NewDeleteChecker])
1927 getCheckIfTracked(C, AllocExpr);
1928 if (!CheckKind.hasValue())
1935 if (!BT_OffsetFree[*CheckKind])
1936 BT_OffsetFree[*CheckKind].reset(
new BugType(
1940 llvm::raw_svector_ostream os(buf);
1942 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1945 assert(MR &&
"Only MemRegion based symbols can have offset free errors");
1951 "Only symbols with a valid offset can have offset free errors");
1955 os <<
"Argument to ";
1956 if (!printAllocDeallocName(os, C, DeallocExpr))
1957 os <<
"deallocator";
1958 os <<
" is offset by " 1961 << ((
abs(offsetBytes) > 1) ?
"bytes" :
"byte")
1962 <<
" from the start of ";
1963 if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1964 os <<
"memory allocated by " << AllocNameOs.str();
1966 os <<
"allocated memory";
1968 auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
1977 if (!ChecksEnabled[CK_MallocChecker] &&
1978 !ChecksEnabled[CK_NewDeleteChecker])
1982 if (!CheckKind.hasValue())
1986 if (!BT_UseFree[*CheckKind])
1987 BT_UseFree[*CheckKind].reset(
new BugType(
1990 auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
1991 "Use of memory after it is freed", N);
1993 R->markInteresting(Sym);
1995 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1997 const RefState *RS = C.
getState()->get<RegionState>(Sym);
1998 if (RS->getAllocationFamily() == AF_InnerBuffer)
2009 if (!ChecksEnabled[CK_MallocChecker] &&
2010 !ChecksEnabled[CK_NewDeleteChecker])
2014 if (!CheckKind.hasValue())
2018 if (!BT_DoubleFree[*CheckKind])
2019 BT_DoubleFree[*CheckKind].reset(
new BugType(
2022 auto R = llvm::make_unique<BugReport>(
2023 *BT_DoubleFree[*CheckKind],
2024 (Released ?
"Attempt to free released memory" 2025 :
"Attempt to free non-owned memory"),
2028 R->markInteresting(Sym);
2030 R->markInteresting(PrevSym);
2031 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2038 if (!ChecksEnabled[CK_NewDeleteChecker])
2042 if (!CheckKind.hasValue())
2046 if (!BT_DoubleDelete)
2047 BT_DoubleDelete.reset(
new BugType(CheckNames[CK_NewDeleteChecker],
2051 auto R = llvm::make_unique<BugReport>(
2052 *BT_DoubleDelete,
"Attempt to delete released memory", N);
2054 R->markInteresting(Sym);
2055 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2064 if (!ChecksEnabled[CK_MallocChecker] &&
2065 !ChecksEnabled[CK_NewDeleteChecker])
2070 if (!CheckKind.hasValue())
2074 if (!BT_UseZerroAllocated[*CheckKind])
2075 BT_UseZerroAllocated[*CheckKind].reset(
2076 new BugType(CheckNames[*CheckKind],
"Use of zero allocated",
2079 auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
2080 "Use of zero-allocated memory", N);
2084 R->markInteresting(Sym);
2085 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2093 const Expr *FreeExpr)
const {
2094 if (!ChecksEnabled[CK_MallocChecker])
2098 if (!CheckKind.hasValue())
2102 if (!BT_BadFree[*CheckKind])
2103 BT_BadFree[*CheckKind].reset(
new BugType(
2107 llvm::raw_svector_ostream Os(Buf);
2110 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2111 MR = ER->getSuperRegion();
2113 Os <<
"Argument to ";
2114 if (!printAllocDeallocName(Os, C, FreeExpr))
2115 Os <<
"deallocator";
2117 Os <<
" is a function pointer";
2119 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str(), N);
2120 R->markInteresting(MR);
2130 bool SuffixWithN)
const {
2148 svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
2156 TotalSize = evalMulForBufferSize(C, Arg1, CE->
getArg(2));
2163 svalBuilder.makeIntValWithPtrWidth(0,
false));
2166 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
2168 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
2171 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
2172 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
2176 if (PrtIsNull && !SizeIsZero) {
2182 if (PrtIsNull && SizeIsZero)
2190 if (!FromPtr || !ToPtr)
2193 bool ReleasedAllocated =
false;
2198 false, ReleasedAllocated)){
2208 FreeMemAux(C, CE, State, 0,
false, ReleasedAllocated)) {
2217 Kind = RPIsFreeOnFailure;
2218 else if (!ReleasedAllocated)
2219 Kind = RPDoNotTrackAfterFailure;
2223 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
2224 ReallocPair(FromPtr, Kind));
2227 return stateRealloc;
2244 return MallocMemAux(C, CE, TotalSize, zeroVal, State);
2254 const MemRegion *ReferenceRegion =
nullptr;
2258 if (!State->get<RegionState>(Sym))
2263 if (!ReferenceRegion) {
2265 SVal Val = State->getSVal(MR);
2272 ReferenceRegion = MR;
2280 if (NContext == LeakContext ||
2286 return LeakInfo(AllocNode, ReferenceRegion);
2292 if (!ChecksEnabled[CK_MallocChecker] &&
2293 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2296 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2297 assert(RS &&
"cannot leak an untracked symbol");
2300 if (Family == AF_Alloca)
2304 CheckKind = getCheckIfTracked(Family,
true);
2306 if (!CheckKind.hasValue())
2310 if (!BT_Leak[*CheckKind]) {
2311 BT_Leak[*CheckKind].reset(
new BugType(CheckNames[*CheckKind],
"Memory leak",
2318 BT_Leak[*CheckKind]->setSuppressOnSink(
true);
2327 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2336 llvm::raw_svector_ostream os(buf);
2338 os <<
"Potential leak of memory pointed to by ";
2341 os <<
"Potential memory leak";
2344 auto R = llvm::make_unique<BugReport>(
2345 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2347 R->markInteresting(Sym);
2348 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym,
true));
2352 void MallocChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
2359 RegionStateTy RS = state->get<RegionState>();
2363 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2364 if (SymReaper.
isDead(I->first)) {
2365 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2366 Errors.push_back(I->first);
2368 RS = F.remove(RS, I->first);
2374 ReallocPairsTy RP = state->get<ReallocPairs>();
2375 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2376 if (SymReaper.
isDead(I->first) ||
2377 SymReaper.
isDead(I->second.ReallocatedSym)) {
2378 state = state->remove<ReallocPairs>(I->first);
2383 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2384 for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
2385 if (SymReaper.
isDead(I->first) ||
2386 SymReaper.
isDead(I->second)) {
2387 state = state->remove<FreeReturnValue>(I->first);
2393 if (!Errors.empty()) {
2398 I = Errors.begin(), E = Errors.end(); I != E; ++I) {
2399 reportLeak(*I, N, C);
2407 void MallocChecker::checkPreCall(
const CallEvent &Call,
2411 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2412 if (!Sym || checkDoubleDelete(Sym, C))
2423 if (ChecksEnabled[CK_MallocChecker] &&
2424 (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
2425 isCMemFunction(FD, Ctx, AF_IfNameIndex,
2426 MemoryOperationKind::MOK_Free)))
2429 if (ChecksEnabled[CK_NewDeleteChecker] &&
2430 isStandardNewDelete(FD, Ctx))
2436 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2437 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2442 for (
unsigned I = 0, E = Call.
getNumArgs(); I != E; ++I) {
2448 if (checkUseAfterFree(Sym, C, Call.
getArgExpr(I)))
2468 if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
2471 Sym = BMR->getSymbol();
2475 checkUseAfterFree(Sym, C, E);
2481 void MallocChecker::checkPostStmt(
const BlockExpr *BE,
2503 for ( ; I != E; ++I) {
2504 const VarRegion *VR = I.getCapturedRegion();
2508 Regions.push_back(VR);
2512 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2513 Regions.data() + Regions.size()).getState();
2519 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2520 return (RS && RS->isReleased());
2524 const Stmt *S)
const {
2526 if (isReleased(Sym, C)) {
2535 const Stmt *S)
const {
2538 if (
const RefState *RS = C.
getState()->get<RegionState>(Sym)) {
2539 if (RS->isAllocatedOfSizeZero())
2540 ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
2542 else if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
2549 if (isReleased(Sym, C)) {
2550 ReportDoubleDelete(C, Sym);
2557 void MallocChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
2561 checkUseAfterFree(Sym, C, S);
2562 checkUseZeroAllocated(Sym, C, S);
2570 bool Assumption)
const {
2571 RegionStateTy RS = state->get<RegionState>();
2572 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2577 state = state->remove<RegionState>(I.getKey());
2582 ReallocPairsTy RP = state->get<ReallocPairs>();
2583 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2590 SymbolRef ReallocSym = I.getData().ReallocatedSym;
2591 if (
const RefState *RS = state->get<RegionState>(ReallocSym)) {
2592 if (RS->isReleased()) {
2593 if (I.getData().Kind == RPToBeFreedAfterFailure)
2594 state = state->set<RegionState>(ReallocSym,
2595 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
2596 else if (I.getData().Kind == RPDoNotTrackAfterFailure)
2597 state = state->remove<RegionState>(ReallocSym);
2599 assert(I.getData().Kind == RPIsFreeOnFailure);
2602 state = state->remove<ReallocPairs>(I.getKey());
2608 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
2613 EscapingSymbol =
nullptr;
2619 if (!(isa<SimpleFunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
2623 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
2639 return *FreeWhenDone;
2645 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
2646 if (FirstSlot.endswith(
"NoCopy"))
2653 if (FirstSlot.startswith(
"addPointer") ||
2654 FirstSlot.startswith(
"insertPointer") ||
2655 FirstSlot.startswith(
"replacePointer") ||
2656 FirstSlot.equals(
"valueWithPointer")) {
2663 if (Msg->getMethodFamily() ==
OMF_init) {
2664 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
2674 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
2678 ASTContext &ASTC = State->getStateManager().getContext();
2682 if (isMemFunction(FD, ASTC))
2693 StringRef FName = II->
getName();
2697 if (FName.endswith(
"NoCopy")) {
2701 for (
unsigned i = 1; i < Call->
getNumArgs(); ++i) {
2703 if (
const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
2704 StringRef DeallocatorName = DE->getFoundDecl()->getName();
2705 if (DeallocatorName ==
"kCFAllocatorNull")
2716 if (FName ==
"funopen")
2723 if (FName ==
"setbuf" || FName ==
"setbuffer" ||
2724 FName ==
"setlinebuf" || FName ==
"setvbuf") {
2727 if (
const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
2728 if (
const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
2729 if (D->getCanonicalDecl()->getName().find(
"std") != StringRef::npos)
2739 if (FName ==
"CGBitmapContextCreate" ||
2740 FName ==
"CGBitmapContextCreateWithData" ||
2741 FName ==
"CVPixelBufferCreateWithBytes" ||
2742 FName ==
"CVPixelBufferCreateWithPlanarBytes" ||
2743 FName ==
"OSAtomicEnqueue") {
2747 if (FName ==
"postEvent" &&
2752 if (FName ==
"postEvent" &&
2757 if (FName ==
"connectImpl" &&
2779 return (RS->getAllocationFamily() == AF_CXXNewArray ||
2780 RS->getAllocationFamily() == AF_CXXNew);
2787 return checkPointerEscapeAux(State, Escaped, Call, Kind, &
retTrue);
2794 return checkPointerEscapeAux(State, Escaped, Call, Kind,
2802 bool(*CheckRefState)(
const RefState*))
const {
2807 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
2813 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2818 if (EscapingSymbol && EscapingSymbol != sym)
2821 if (
const RefState *RS = State->get<RegionState>(sym)) {
2822 if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
2823 CheckRefState(RS)) {
2824 State = State->remove<RegionState>(sym);
2825 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2834 ReallocPairsTy currMap = currState->get<ReallocPairs>();
2835 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2837 for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end();
2840 if (!currMap.lookup(sym))
2849 StringRef N = II->getName();
2850 if (N.contains_lower(
"ptr") || N.contains_lower(
"pointer")) {
2851 if (N.contains_lower(
"ref") || N.contains_lower(
"cnt") ||
2852 N.contains_lower(
"intrusive") || N.contains_lower(
"shared")) {
2860 std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
2867 const RefState *RS = state->get<RegionState>(Sym);
2868 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2873 if (!S && (!RS || RS->getAllocationFamily() != AF_InnerBuffer))
2885 if (ReleaseDestructorLC) {
2886 if (
const auto *AE = dyn_cast<AtomicExpr>(S)) {
2888 if (Op == AtomicExpr::AO__c11_atomic_fetch_add ||
2889 Op == AtomicExpr::AO__c11_atomic_fetch_sub) {
2890 if (ReleaseDestructorLC == CurrentLC ||
2891 ReleaseDestructorLC->
isParentOf(CurrentLC)) {
2905 llvm::raw_svector_ostream OS(Buf);
2907 if (Mode == Normal) {
2908 if (isAllocated(RS, RSPrev, S)) {
2909 Msg =
"Memory is allocated";
2911 "Returned allocated memory");
2912 }
else if (isReleased(RS, RSPrev, S)) {
2913 const auto Family = RS->getAllocationFamily();
2918 case AF_CXXNewArray:
2919 case AF_IfNameIndex:
2920 Msg =
"Memory is released";
2922 case AF_InnerBuffer: {
2923 OS <<
"Inner pointer invalidated by call to ";
2928 const Stmt *S = RS->getStmt();
2929 if (
const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
2930 OS << MemCallE->getMethodDecl()->getNameAsString();
2931 }
else if (
const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
2932 OS << OpCallE->getDirectCallee()->getNameAsString();
2933 }
else if (
const auto *CallE = dyn_cast<CallExpr>(S)) {
2935 CallEventRef<> Call = CEMgr.getSimpleCall(CallE, state, CurrentLC);
2936 const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl());
2937 OS << (D ? D->getNameAsString() :
"unknown");
2945 llvm_unreachable(
"Unhandled allocation family!");
2948 "Returning; memory was released");
2953 bool FoundAnyDestructor =
false;
2955 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
2961 }
else if (!FoundAnyDestructor) {
2962 assert(!ReleaseDestructorLC &&
2963 "There can be only one release point!");
2969 ReleaseDestructorLC = LC->getStackFrame();
2975 FoundAnyDestructor =
true;
2979 }
else if (isRelinquished(RS, RSPrev, S)) {
2980 Msg =
"Memory ownership is transferred";
2982 }
else if (isReallocFailedCheck(RS, RSPrev, S)) {
2983 Mode = ReallocationFailed;
2984 Msg =
"Reallocation failed";
2985 StackHint =
new StackHintGeneratorForReallocationFailed(Sym,
2986 "Reallocation failed");
2990 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
2991 "We only support one failed realloc at a time.");
2993 FailedReallocSymbol = sym;
2998 }
else if (Mode == ReallocationFailed) {
2999 assert(FailedReallocSymbol &&
"No symbol to look for.");
3002 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
3004 Msg =
"Attempt to reallocate memory";
3006 "Returned reallocated memory");
3007 FailedReallocSymbol =
nullptr;
3019 assert(RS->getAllocationFamily() == AF_InnerBuffer);
3030 return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg,
true, StackHint);
3033 void MallocChecker::printState(raw_ostream &Out,
ProgramStateRef State,
3034 const char *NL,
const char *Sep)
const {
3036 RegionStateTy RS = State->get<RegionState>();
3038 if (!RS.isEmpty()) {
3039 Out << Sep <<
"MallocChecker :" << NL;
3040 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
3041 const RefState *RefS = State->get<RegionState>(I.getKey());
3044 if (!CheckKind.hasValue())
3045 CheckKind = getCheckIfTracked(Family,
true);
3047 I.getKey()->dumpToStream(Out);
3049 I.getData().dump(Out);
3050 if (CheckKind.hasValue())
3051 Out <<
" (" << CheckNames[*CheckKind].
getName() <<
")";
3059 namespace allocation_state {
3064 return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
3075 "Optimistic",
false, checker);
3076 checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] =
true;
3077 checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
3081 if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
3082 checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] =
true;
3085 checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
3090 #define REGISTER_CHECKER(name) \ 3091 void ento::register##name(CheckerManager &mgr) { \ 3092 registerCStringCheckerBasic(mgr); \ 3093 MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \ 3094 checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \ 3095 "Optimistic", false, checker); \ 3096 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \ 3097 checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
const BlockDecl * getBlockDecl() const
Represents 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
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
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.
A Range represents the closed range [from, to].
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...
constexpr XRayInstrMask Function
AnalysisManager & getAnalysisManager()
const ProgramStateRef & getState() const
Represents a C++ constructor within a class.
Value representing integer constant.
bool isConsumedExpr(Expr *E) const
Represents 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.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
#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
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 ...
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.
std::unique_ptr< BugReporterVisitor > getInnerPointerBRVisitor(SymbolRef Sym)
This function provides an additional visitor that augments the bug report with information relevant t...
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 LocationContext * getLocationContext() const
const LocationContext * getParent() const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD)
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 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.
Represents a C++ destructor within a class.
AnalyzerOptions & getAnalyzerOptions() override
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...
CHECKER * registerChecker(AT... Args)
Used to register checkers.
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.
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)"...
CallEventManager & getCallEventManager()
ASTContext & getContext()
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
QualType getAllocatedType() const
const ParmVarDecl * getParamDecl(unsigned i) const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
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. ...
Represents a program point just after an implicit call event.
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...
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)
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.
ProgramStateManager & getStateManager()
static Optional< bool > getFreeWhenDoneArg(const ObjCMethodCall &Call)
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
const StackFrameContext * getStackFrame() const
ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin)
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
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.
void markInvalid(const void *Tag, const void *Data)
Marks the current report as invalid, meaning that it is probably a false positive and should not be r...
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
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...
static llvm::ImmutableListFactory< const FieldRegion * > Factory
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
bool mayInlineCXXAllocator()
Returns whether or not allocator call may be considered for inlining.
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.
This represents a decl that may have a name.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
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>.