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>,
166 check::PostStmt<CallExpr>,
167 check::PostStmt<CXXNewExpr>,
169 check::PreStmt<CXXDeleteExpr>,
170 check::PostStmt<BlockExpr>,
171 check::PostObjCMessage,
177 : II_alloca(
nullptr), II_win_alloca(
nullptr), II_malloc(
nullptr),
178 II_free(
nullptr), II_realloc(
nullptr), II_calloc(
nullptr),
179 II_valloc(
nullptr), II_reallocf(
nullptr), II_strndup(
nullptr),
180 II_strdup(
nullptr), II_win_strdup(
nullptr), II_kmalloc(
nullptr),
181 II_if_nameindex(
nullptr), II_if_freenameindex(
nullptr),
182 II_wcsdup(
nullptr), II_win_wcsdup(
nullptr), II_g_malloc(
nullptr),
183 II_g_malloc0(
nullptr), II_g_realloc(
nullptr), II_g_try_malloc(
nullptr),
184 II_g_try_malloc0(
nullptr), II_g_try_realloc(
nullptr),
185 II_g_free(
nullptr), II_g_memdup(
nullptr), II_g_malloc_n(
nullptr),
186 II_g_malloc0_n(
nullptr), II_g_realloc_n(
nullptr),
187 II_g_try_malloc_n(
nullptr), II_g_try_malloc0_n(
nullptr),
188 II_g_try_realloc_n(
nullptr) {}
195 CK_NewDeleteLeaksChecker,
196 CK_MismatchedDeallocatorChecker,
197 CK_InnerPointerChecker,
201 enum class MemoryOperationKind {
207 DefaultBool IsOptimistic;
209 DefaultBool ChecksEnabled[CK_NumCheckKinds];
210 CheckName CheckNames[CK_NumCheckKinds];
212 void checkPreCall(
const CallEvent &Call, CheckerContext &C)
const;
213 void checkPostStmt(
const CallExpr *CE, CheckerContext &C)
const;
214 void checkPostStmt(
const CXXNewExpr *NE, CheckerContext &C)
const;
216 CheckerContext &C)
const;
217 void checkPreStmt(
const CXXDeleteExpr *DE, CheckerContext &C)
const;
218 void checkPostObjCMessage(
const ObjCMethodCall &Call, CheckerContext &C)
const;
219 void checkPostStmt(
const BlockExpr *BE, CheckerContext &C)
const;
220 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C)
const;
221 void checkPreStmt(
const ReturnStmt *S, CheckerContext &C)
const;
222 void checkEndFunction(
const ReturnStmt *S, CheckerContext &C)
const;
224 bool Assumption)
const;
225 void checkLocation(SVal l,
bool isLoad,
const Stmt *S,
226 CheckerContext &C)
const;
238 const char *NL,
const char *Sep)
const override;
241 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
242 mutable std::unique_ptr<BugType> BT_DoubleDelete;
243 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
244 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
245 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
246 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
247 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
248 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
249 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
250 mutable IdentifierInfo *II_alloca, *II_win_alloca, *II_malloc, *II_free,
251 *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
252 *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
253 *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
254 *II_win_wcsdup, *II_g_malloc, *II_g_malloc0,
255 *II_g_realloc, *II_g_try_malloc, *II_g_try_malloc0,
256 *II_g_try_realloc, *II_g_free, *II_g_memdup,
257 *II_g_malloc_n, *II_g_malloc0_n, *II_g_realloc_n,
258 *II_g_try_malloc_n, *II_g_try_malloc0_n,
270 bool printAllocDeallocName(raw_ostream &os, CheckerContext &C,
271 const Expr *E)
const;
275 void printExpectedAllocName(raw_ostream &os, CheckerContext &C,
276 const Expr *DeallocExpr)
const;
279 void printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family)
const;
288 MemoryOperationKind MemKind)
const;
294 void processNewAllocation(
const CXXNewExpr *NE, CheckerContext &C,
301 const unsigned AllocationSizeArg,
307 const OwnershipAttr* Att,
310 const Expr *SizeEx, SVal Init,
314 SVal SizeEx, SVal Init,
324 performKernelMalloc(
const CallExpr *CE, CheckerContext &C,
336 const OwnershipAttr* Att,
341 bool &ReleasedAllocated,
342 bool ReturnsNullOnFailure =
false)
const;
344 const Expr *ParentExpr,
347 bool &ReleasedAllocated,
348 bool ReturnsNullOnFailure =
false)
const;
351 bool FreesMemOnFailure,
353 bool SuffixWithN =
false)
const;
354 static SVal evalMulForBufferSize(CheckerContext &C,
const Expr *Blocks,
355 const Expr *BlockBytes);
360 bool isReleased(
SymbolRef Sym, CheckerContext &C)
const;
362 bool checkUseAfterFree(
SymbolRef Sym, CheckerContext &C,
const Stmt *S)
const;
364 void checkUseZeroAllocated(
SymbolRef Sym, CheckerContext &C,
365 const Stmt *S)
const;
367 bool checkDoubleDelete(
SymbolRef Sym, CheckerContext &C)
const;
379 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
const CallEvent *Call,
388 bool(*CheckRefState)(
const RefState*))
const;
391 void checkEscapeOnReturn(
const ReturnStmt *S, CheckerContext &C)
const;
398 bool IsALeakCheck =
false)
const;
400 const Stmt *AllocDeallocStmt,
401 bool IsALeakCheck =
false)
const;
403 bool IsALeakCheck =
false)
const;
405 static bool SummarizeValue(raw_ostream &os, SVal V);
406 static bool SummarizeRegion(raw_ostream &os,
const MemRegion *MR);
407 void ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange Range,
408 const Expr *DeallocExpr)
const;
409 void ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
411 void ReportMismatchedDealloc(CheckerContext &C,
SourceRange Range,
412 const Expr *DeallocExpr,
const RefState *RS,
413 SymbolRef Sym,
bool OwnershipTransferred)
const;
414 void ReportOffsetFree(CheckerContext &C, SVal ArgVal,
SourceRange Range,
415 const Expr *DeallocExpr,
416 const Expr *AllocExpr =
nullptr)
const;
417 void ReportUseAfterFree(CheckerContext &C,
SourceRange Range,
419 void ReportDoubleFree(CheckerContext &C,
SourceRange Range,
bool Released,
422 void ReportDoubleDelete(CheckerContext &C,
SymbolRef Sym)
const;
424 void ReportUseZeroAllocated(CheckerContext &C,
SourceRange Range,
427 void ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
432 LeakInfo getAllocationSite(
const ExplodedNode *N,
SymbolRef Sym,
433 CheckerContext &C)
const;
435 void reportLeak(
SymbolRef Sym, ExplodedNode *N, CheckerContext &C)
const;
442 enum NotificationMode {
451 NotificationMode Mode;
463 MallocBugVisitor(
SymbolRef S,
bool isLeak =
false)
464 : Sym(S), Mode(Normal), FailedReallocSymbol(
nullptr),
465 ReleaseDestructorLC(
nullptr), IsLeak(isLeak) {}
467 static void *getTag() {
472 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
473 ID.AddPointer(getTag());
477 inline bool isAllocated(
const RefState *S,
const RefState *SPrev,
480 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
481 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
482 (!SPrev || !(SPrev->isAllocated() ||
483 SPrev->isAllocatedOfSizeZero())));
486 inline bool isReleased(
const RefState *S,
const RefState *SPrev,
490 bool IsReleased = (S && S->isReleased()) &&
491 (!SPrev || !SPrev->isReleased());
492 assert(!IsReleased ||
493 (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt))) ||
494 (!Stmt && S->getAllocationFamily() == AF_InnerBuffer));
498 inline bool isRelinquished(
const RefState *S,
const RefState *SPrev,
501 return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
502 isa<ObjCPropertyRefExpr>(Stmt)) &&
503 (S && S->isRelinquished()) &&
504 (!SPrev || !SPrev->isRelinquished()));
507 inline bool isReallocFailedCheck(
const RefState *S,
const RefState *SPrev,
513 return ((!Stmt || !isa<CallExpr>(Stmt)) &&
514 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
515 (SPrev && !(SPrev->isAllocated() ||
516 SPrev->isAllocatedOfSizeZero())));
519 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
520 BugReporterContext &BRC,
521 BugReport &BR)
override;
523 std::shared_ptr<PathDiagnosticPiece>
524 getEndPath(BugReporterContext &BRC,
const ExplodedNode *EndPathNode,
525 BugReport &BR)
override {
529 PathDiagnosticLocation L =
531 BRC.getSourceManager());
533 return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
538 class StackHintGeneratorForReallocationFailed
539 :
public StackHintGeneratorForSymbol {
541 StackHintGeneratorForReallocationFailed(
SymbolRef S, StringRef M)
542 : StackHintGeneratorForSymbol(S, M) {}
544 std::string getMessageForArg(
const Expr *ArgE,
545 unsigned ArgIndex)
override {
550 llvm::raw_svector_ostream os(buf);
552 os <<
"Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
553 <<
" parameter failed";
559 return "Reallocation of returned value failed";
575 class StopTrackingCallback final :
public SymbolVisitor {
581 bool VisitSymbol(
SymbolRef sym)
override {
582 state = state->remove<RegionState>(sym);
588 void MallocChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
595 II_reallocf = &Ctx.
Idents.
get(
"reallocf");
602 II_if_nameindex = &Ctx.
Idents.
get(
"if_nameindex");
603 II_if_freenameindex = &Ctx.
Idents.
get(
"if_freenameindex");
606 II_win_strdup = &Ctx.
Idents.
get(
"_strdup");
607 II_win_wcsdup = &Ctx.
Idents.
get(
"_wcsdup");
608 II_win_alloca = &Ctx.
Idents.
get(
"_alloca");
611 II_g_malloc = &Ctx.
Idents.
get(
"g_malloc");
612 II_g_malloc0 = &Ctx.
Idents.
get(
"g_malloc0");
613 II_g_realloc = &Ctx.
Idents.
get(
"g_realloc");
614 II_g_try_malloc = &Ctx.
Idents.
get(
"g_try_malloc");
615 II_g_try_malloc0 = &Ctx.
Idents.
get(
"g_try_malloc0");
616 II_g_try_realloc = &Ctx.
Idents.
get(
"g_try_realloc");
618 II_g_memdup = &Ctx.
Idents.
get(
"g_memdup");
619 II_g_malloc_n = &Ctx.
Idents.
get(
"g_malloc_n");
620 II_g_malloc0_n = &Ctx.
Idents.
get(
"g_malloc0_n");
621 II_g_realloc_n = &Ctx.
Idents.
get(
"g_realloc_n");
622 II_g_try_malloc_n = &Ctx.
Idents.
get(
"g_try_malloc_n");
623 II_g_try_malloc0_n = &Ctx.
Idents.
get(
"g_try_malloc0_n");
624 II_g_try_realloc_n = &Ctx.
Idents.
get(
"g_try_realloc_n");
628 if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any))
631 if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
634 if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
637 if (isStandardNewDelete(FD, C))
643 bool MallocChecker::isCMemFunction(
const FunctionDecl *FD,
646 MemoryOperationKind MemKind)
const {
650 bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any ||
651 MemKind == MemoryOperationKind::MOK_Free);
652 bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any ||
653 MemKind == MemoryOperationKind::MOK_Allocate);
657 initIdentifierInfo(C);
659 if (Family == AF_Malloc && CheckFree) {
660 if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
665 if (Family == AF_Malloc && CheckAlloc) {
666 if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
667 FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
668 FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
669 FunI == II_win_wcsdup || FunI == II_kmalloc ||
670 FunI == II_g_malloc || FunI == II_g_malloc0 ||
671 FunI == II_g_realloc || FunI == II_g_try_malloc ||
672 FunI == II_g_try_malloc0 || FunI == II_g_try_realloc ||
673 FunI == II_g_memdup || FunI == II_g_malloc_n ||
674 FunI == II_g_malloc0_n || FunI == II_g_realloc_n ||
675 FunI == II_g_try_malloc_n || FunI == II_g_try_malloc0_n ||
676 FunI == II_g_try_realloc_n)
680 if (Family == AF_IfNameIndex && CheckFree) {
681 if (FunI == II_if_freenameindex)
685 if (Family == AF_IfNameIndex && CheckAlloc) {
686 if (FunI == II_if_nameindex)
690 if (Family == AF_Alloca && CheckAlloc) {
691 if (FunI == II_alloca || FunI == II_win_alloca)
696 if (Family != AF_Malloc)
699 if (IsOptimistic && FD->
hasAttrs()) {
701 OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
702 if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
705 }
else if (OwnKind == OwnershipAttr::Returns) {
717 bool MallocChecker::isStandardNewDelete(
const FunctionDecl *FD,
723 if (Kind != OO_New && Kind != OO_Array_New &&
724 Kind != OO_Delete && Kind != OO_Array_Delete)
755 if (!KernelZeroFlagVal.hasValue()) {
756 if (OS == llvm::Triple::FreeBSD)
757 KernelZeroFlagVal = 0x0100;
758 else if (OS == llvm::Triple::NetBSD)
759 KernelZeroFlagVal = 0x0002;
760 else if (OS == llvm::Triple::OpenBSD)
761 KernelZeroFlagVal = 0x0008;
762 else if (OS == llvm::Triple::Linux)
764 KernelZeroFlagVal = 0x8000;
781 const SVal V = C.getSVal(FlagsEx);
782 if (!V.getAs<NonLoc>()) {
788 NonLoc Flags = V.castAs<NonLoc>();
789 NonLoc ZeroFlag = C.getSValBuilder()
790 .makeIntVal(KernelZeroFlagVal.getValue(), FlagsEx->
getType())
792 SVal MaskedFlagsUC = C.getSValBuilder().evalBinOpNN(State, BO_And,
795 if (MaskedFlagsUC.isUnknownOrUndef())
797 DefinedSVal MaskedFlags = MaskedFlagsUC.castAs<DefinedSVal>();
801 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
804 if (TrueState && !FalseState) {
805 SVal ZeroVal = C.getSValBuilder().makeZeroVal(Ctx.
CharTy);
806 return MallocMemAux(C, CE, CE->
getArg(0), ZeroVal, TrueState);
812 SVal MallocChecker::evalMulForBufferSize(CheckerContext &C,
const Expr *Blocks,
813 const Expr *BlockBytes) {
814 SValBuilder &SB = C.getSValBuilder();
815 SVal BlocksVal = C.getSVal(Blocks);
816 SVal BlockBytesVal = C.getSVal(BlockBytes);
818 SVal TotalSize = SB.evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,
819 SB.getContext().getSizeType());
823 void MallocChecker::checkPostStmt(
const CallExpr *CE, CheckerContext &C)
const {
832 bool ReleasedAllocatedMemory =
false;
835 initIdentifierInfo(C.getASTContext());
838 if (FunI == II_malloc || FunI == II_g_malloc || FunI == II_g_try_malloc) {
842 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State);
844 State = ProcessZeroAllocation(C, CE, 0, State);
847 performKernelMalloc(CE, C, State);
848 if (MaybeState.hasValue())
849 State = MaybeState.getValue();
851 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State);
853 }
else if (FunI == II_kmalloc) {
857 performKernelMalloc(CE, C, State);
858 if (MaybeState.hasValue())
859 State = MaybeState.getValue();
861 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State);
862 }
else if (FunI == II_valloc) {
865 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State);
866 State = ProcessZeroAllocation(C, CE, 0, State);
867 }
else if (FunI == II_realloc || FunI == II_g_realloc ||
868 FunI == II_g_try_realloc) {
869 State = ReallocMemAux(C, CE,
false, State);
870 State = ProcessZeroAllocation(C, CE, 1, State);
871 }
else if (FunI == II_reallocf) {
872 State = ReallocMemAux(C, CE,
true, State);
873 State = ProcessZeroAllocation(C, CE, 1, State);
874 }
else if (FunI == II_calloc) {
875 State = CallocMem(C, CE, State);
876 State = ProcessZeroAllocation(C, CE, 0, State);
877 State = ProcessZeroAllocation(C, CE, 1, State);
878 }
else if (FunI == II_free || FunI == II_g_free) {
879 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
880 }
else if (FunI == II_strdup || FunI == II_win_strdup ||
881 FunI == II_wcsdup || FunI == II_win_wcsdup) {
882 State = MallocUpdateRefState(C, CE, State);
883 }
else if (FunI == II_strndup) {
884 State = MallocUpdateRefState(C, CE, State);
885 }
else if (FunI == II_alloca || FunI == II_win_alloca) {
888 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State,
890 State = ProcessZeroAllocation(C, CE, 0, State);
898 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State,
900 State = ProcessZeroAllocation(C, CE, 0, State);
902 else if (K == OO_Array_New) {
903 State = MallocMemAux(C, CE, CE->
getArg(0), UndefinedVal(),
State,
905 State = ProcessZeroAllocation(C, CE, 0, State);
907 else if (K == OO_Delete || K == OO_Array_Delete)
908 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
910 llvm_unreachable(
"not a new/delete operator");
911 }
else if (FunI == II_if_nameindex) {
914 State = MallocMemAux(C, CE, UnknownVal(), UnknownVal(), State,
916 }
else if (FunI == II_if_freenameindex) {
917 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
918 }
else if (FunI == II_g_malloc0 || FunI == II_g_try_malloc0) {
921 SValBuilder &svalBuilder = C.getSValBuilder();
922 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
923 State = MallocMemAux(C, CE, CE->
getArg(0), zeroVal,
State);
924 State = ProcessZeroAllocation(C, CE, 0, State);
925 }
else if (FunI == II_g_memdup) {
928 State = MallocMemAux(C, CE, CE->
getArg(1), UndefinedVal(),
State);
929 State = ProcessZeroAllocation(C, CE, 1, State);
930 }
else if (FunI == II_g_malloc_n || FunI == II_g_try_malloc_n ||
931 FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
934 SVal Init = UndefinedVal();
935 if (FunI == II_g_malloc0_n || FunI == II_g_try_malloc0_n) {
936 SValBuilder &SB = C.getSValBuilder();
937 Init = SB.makeZeroVal(SB.getContext().CharTy);
939 SVal TotalSize = evalMulForBufferSize(C, CE->
getArg(0), CE->
getArg(1));
940 State = MallocMemAux(C, CE, TotalSize, Init, State);
941 State = ProcessZeroAllocation(C, CE, 0, State);
942 State = ProcessZeroAllocation(C, CE, 1, State);
943 }
else if (FunI == II_g_realloc_n || FunI == II_g_try_realloc_n) {
946 State = ReallocMemAux(C, CE,
false, State,
true);
947 State = ProcessZeroAllocation(C, CE, 1, State);
948 State = ProcessZeroAllocation(C, CE, 2, State);
952 if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
957 switch (I->getOwnKind()) {
958 case OwnershipAttr::Returns:
959 State = MallocMemReturnsAttr(C, CE, I, State);
961 case OwnershipAttr::Takes:
962 case OwnershipAttr::Holds:
963 State = FreeMemAttr(C, CE, I, State);
968 C.addTransition(State);
973 CheckerContext &C,
const Expr *E,
const unsigned AllocationSizeArg,
979 RetVal = C.getSVal(E);
981 const Expr *Arg =
nullptr;
983 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
984 Arg = CE->
getArg(AllocationSizeArg);
986 else if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
988 Arg = NE->getArraySize();
993 llvm_unreachable(
"not a CallExpr or CXXNewExpr");
1004 SValBuilder &SvalBuilder = C.getSValBuilder();
1006 SvalBuilder.makeZeroVal(Arg->
getType()).castAs<DefinedSVal>();
1008 std::tie(TrueState, FalseState) =
1009 State->assume(SvalBuilder.evalEQ(
State, *DefArgVal, Zero));
1011 if (TrueState && !FalseState) {
1012 SymbolRef Sym = RetVal->getAsLocSymbol();
1016 const RefState *RS =
State->get<RegionState>(Sym);
1018 if (RS->isAllocated())
1019 return TrueState->set<RegionState>(Sym,
1020 RefState::getAllocatedOfSizeZero(RS));
1028 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
1039 while (!PointeeType.isNull()) {
1040 Result = PointeeType;
1058 for (
const auto *CtorParam : CtorD->
parameters()) {
1061 if (CtorParamPointeeT.
isNull())
1073 void MallocChecker::processNewAllocation(
const CXXNewExpr *NE,
1076 if (!isStandardNewDelete(NE->
getOperatorNew(), C.getASTContext()))
1079 ParentMap &PM = C.getLocationContext()->getParentMap();
1088 State = MallocUpdateRefState(C, NE, State, NE->
isArray() ? AF_CXXNewArray
1089 : AF_CXXNew, Target);
1090 State = addExtentSize(C, NE, State, Target);
1091 State = ProcessZeroAllocation(C, NE, 0, State, Target);
1092 C.addTransition(State);
1095 void MallocChecker::checkPostStmt(
const CXXNewExpr *NE,
1096 CheckerContext &C)
const {
1097 if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator)
1098 processNewAllocation(NE, C, C.getSVal(NE));
1102 CheckerContext &C)
const {
1104 processNewAllocation(NE, C,
Target);
1116 SValBuilder &svalBuilder = C.getSValBuilder();
1118 const SubRegion *Region;
1121 ElementCount = C.getSVal(SizeExpr);
1124 Region = Target.getAsRegion()
1125 ->getAs<SubRegion>()
1127 ->getAs<SubRegion>();
1129 ElementCount = svalBuilder.makeIntVal(1,
true);
1130 Region = Target.getAsRegion()->getAs<SubRegion>();
1139 if (ElementCount.getAs<NonLoc>()) {
1140 DefinedOrUnknownSVal Extent = Region->getExtent(svalBuilder);
1142 SVal SizeInBytes = svalBuilder.evalBinOpNN(
1143 State, BO_Mul, ElementCount.castAs<NonLoc>(),
1144 svalBuilder.makeArrayIndex(TypeSize.
getQuantity()),
1145 svalBuilder.getArrayIndexType());
1146 DefinedOrUnknownSVal extentMatchesSize = svalBuilder.evalEQ(
1147 State, Extent, SizeInBytes.castAs<DefinedOrUnknownSVal>());
1148 State =
State->assume(extentMatchesSize,
true);
1154 CheckerContext &C)
const {
1156 if (!ChecksEnabled[CK_NewDeleteChecker])
1164 bool ReleasedAllocated;
1166 false, ReleasedAllocated);
1168 C.addTransition(State);
1178 return FirstSlot ==
"dataWithBytesNoCopy" ||
1179 FirstSlot ==
"initWithBytesNoCopy" ||
1180 FirstSlot ==
"initWithCharactersNoCopy";
1187 for (
unsigned i = 1; i < S.
getNumArgs(); ++i)
1189 return !Call.getArgSVal(i).isZeroConstant();
1194 void MallocChecker::checkPostObjCMessage(
const ObjCMethodCall &Call,
1195 CheckerContext &C)
const {
1206 bool ReleasedAllocatedMemory;
1209 true, ReleasedAllocatedMemory,
1212 C.addTransition(State);
1216 MallocChecker::MallocMemReturnsAttr(CheckerContext &C,
const CallExpr *CE,
1217 const OwnershipAttr *Att,
1222 if (Att->getModule() != II_malloc)
1225 OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
1227 return MallocMemAux(C, CE, CE->
getArg(I->getASTIndex()), UndefinedVal(),
1230 return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
1235 const Expr *SizeEx, SVal Init,
1241 return MallocMemAux(C, CE, C.getSVal(SizeEx), Init,
State, Family);
1246 SVal Size, SVal Init,
1259 unsigned Count = C.blockCount();
1260 SValBuilder &svalBuilder = C.getSValBuilder();
1261 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
1262 DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
1263 .castAs<DefinedSVal>();
1264 State = State->BindExpr(CE, C.getLocationContext(), RetVal);
1267 State = State->bindDefaultInitial(RetVal, Init, LCtx);
1270 const SymbolicRegion *R =
1271 dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
1275 Size.getAs<DefinedOrUnknownSVal>()) {
1276 SValBuilder &svalBuilder = C.getSValBuilder();
1277 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
1278 DefinedOrUnknownSVal extentMatchesSize =
1279 svalBuilder.evalEQ(State, Extent, *DefinedSize);
1281 State = State->assume(extentMatchesSize,
true);
1285 return MallocUpdateRefState(C, CE, State, Family);
1288 ProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
1298 RetVal = C.getSVal(E);
1301 if (!RetVal->getAs<Loc>())
1304 SymbolRef Sym = RetVal->getAsLocSymbol();
1310 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1315 const OwnershipAttr *Att,
1320 if (Att->getModule() != II_malloc)
1323 bool ReleasedAllocated =
false;
1325 for (
const auto &Arg : Att->args()) {
1327 C, CE, State, Arg.getASTIndex(),
1328 Att->getOwnKind() == OwnershipAttr::Holds, ReleasedAllocated);
1340 bool &ReleasedAllocated,
1341 bool ReturnsNullOnFailure)
const {
1348 return FreeMemAux(C, CE->
getArg(Num), CE,
State, Hold,
1349 ReleasedAllocated, ReturnsNullOnFailure);
1356 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1358 assert(*Ret &&
"We should not store the null return symbol");
1359 ConstraintManager &CMgr = State->getConstraintManager();
1360 ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret);
1361 RetStatusSymbol = *Ret;
1362 return FreeFailed.isConstrainedTrue();
1368 const Stmt *S)
const {
1372 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1380 if (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Any))
1383 if (isStandardNewDelete(FD, Ctx)) {
1385 if (Kind == OO_New || Kind == OO_Delete)
1387 else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
1388 return AF_CXXNewArray;
1391 if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
1392 return AF_IfNameIndex;
1394 if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
1400 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
1401 return NE->
isArray() ? AF_CXXNewArray : AF_CXXNew;
1404 return DE->
isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
1406 if (isa<ObjCMessageExpr>(S))
1412 bool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C,
1413 const Expr *E)
const {
1414 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1421 if (!FD->isOverloadedOperator())
1427 if (Msg->isInstanceMessage())
1431 Msg->getSelector().
print(os);
1435 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1452 void MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C,
1453 const Expr *E)
const {
1457 case AF_Malloc: os <<
"malloc()";
return;
1458 case AF_CXXNew: os <<
"'new'";
return;
1459 case AF_CXXNewArray: os <<
"'new[]'";
return;
1460 case AF_IfNameIndex: os <<
"'if_nameindex()'";
return;
1461 case AF_InnerBuffer: os <<
"container-specific allocator";
return;
1463 case AF_None: llvm_unreachable(
"not a deallocation expression");
1467 void MallocChecker::printExpectedDeallocName(raw_ostream &os,
1470 case AF_Malloc: os <<
"free()";
return;
1471 case AF_CXXNew: os <<
"'delete'";
return;
1472 case AF_CXXNewArray: os <<
"'delete[]'";
return;
1473 case AF_IfNameIndex: os <<
"'if_freenameindex()'";
return;
1474 case AF_InnerBuffer: os <<
"container-specific deallocator";
return;
1476 case AF_None: llvm_unreachable(
"suspicious argument");
1481 const Expr *ArgExpr,
1482 const Expr *ParentExpr,
1485 bool &ReleasedAllocated,
1486 bool ReturnsNullOnFailure)
const {
1491 SVal ArgVal = C.getSVal(ArgExpr);
1492 if (!ArgVal.getAs<DefinedOrUnknownSVal>())
1494 DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
1497 if (!location.getAs<Loc>())
1502 std::tie(notNullState, nullState) =
State->assume(location);
1503 if (nullState && !notNullState)
1508 if (ArgVal.isUnknownOrUndef())
1511 const MemRegion *R = ArgVal.getAsRegion();
1520 R = R->StripCasts();
1523 if (isa<BlockDataRegion>(R)) {
1528 const MemSpaceRegion *MS = R->getMemorySpace();
1532 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1541 if (isa<AllocaRegion>(R))
1549 const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
1555 SymbolRef SymBase = SrBase->getSymbol();
1556 const RefState *RsBase =
State->get<RegionState>(SymBase);
1557 SymbolRef PreviousRetStatusSymbol =
nullptr;
1562 if (RsBase->getAllocationFamily() == AF_Alloca) {
1568 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1570 ReportDoubleFree(C, ParentExpr->
getSourceRange(), RsBase->isReleased(),
1571 SymBase, PreviousRetStatusSymbol);
1576 }
else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
1577 RsBase->isEscaped()) {
1580 bool DeallocMatchesAlloc =
1581 RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1582 if (!DeallocMatchesAlloc) {
1584 ParentExpr, RsBase, SymBase, Hold);
1590 RegionOffset
Offset = R->getAsOffset();
1591 if (Offset.isValid() &&
1592 !Offset.hasSymbolicOffset() &&
1593 Offset.getOffset() != 0) {
1594 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1595 ReportOffsetFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr,
1602 if (SymBase->getType()->isFunctionPointerType()) {
1603 ReportFunctionPointerFree(C, ArgVal, ArgExpr->
getSourceRange(), ParentExpr);
1607 ReleasedAllocated = (RsBase !=
nullptr) && (RsBase->isAllocated() ||
1608 RsBase->isAllocatedOfSizeZero());
1611 State =
State->remove<FreeReturnValue>(SymBase);
1615 if (ReturnsNullOnFailure) {
1616 SVal RetVal = C.getSVal(ParentExpr);
1617 SymbolRef RetStatusSymbol = RetVal.getAsSymbol();
1618 if (RetStatusSymbol) {
1619 C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol);
1620 State =
State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1625 : getAllocationFamily(C, ParentExpr);
1628 return State->set<RegionState>(SymBase,
1629 RefState::getRelinquished(Family,
1632 return State->set<RegionState>(SymBase,
1633 RefState::getReleased(Family, ParentExpr));
1638 bool IsALeakCheck)
const {
1642 case AF_IfNameIndex: {
1643 if (ChecksEnabled[CK_MallocChecker])
1644 return CK_MallocChecker;
1648 case AF_CXXNewArray: {
1650 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
1651 return CK_NewDeleteLeaksChecker;
1654 if (ChecksEnabled[CK_NewDeleteChecker])
1655 return CK_NewDeleteChecker;
1659 case AF_InnerBuffer: {
1660 if (ChecksEnabled[CK_InnerPointerChecker])
1661 return CK_InnerPointerChecker;
1665 llvm_unreachable(
"no family");
1668 llvm_unreachable(
"unhandled family");
1672 MallocChecker::getCheckIfTracked(CheckerContext &C,
1673 const Stmt *AllocDeallocStmt,
1674 bool IsALeakCheck)
const {
1675 return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
1680 MallocChecker::getCheckIfTracked(CheckerContext &C,
SymbolRef Sym,
1681 bool IsALeakCheck)
const {
1682 if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym))
1683 return CK_MallocChecker;
1685 const RefState *RS = C.getState()->get<RegionState>(Sym);
1687 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
1690 bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
1692 os <<
"an integer (" << IntVal->getValue() <<
")";
1694 os <<
"a constant address (" << ConstAddr->getValue() <<
")";
1696 os <<
"the address of the label '" <<
Label->getLabel()->getName() <<
"'";
1703 bool MallocChecker::SummarizeRegion(raw_ostream &os,
1704 const MemRegion *MR) {
1705 switch (MR->getKind()) {
1706 case MemRegion::FunctionCodeRegionKind: {
1707 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1709 os <<
"the address of the function '" << *FD <<
'\'';
1711 os <<
"the address of a function";
1714 case MemRegion::BlockCodeRegionKind:
1717 case MemRegion::BlockDataRegionKind:
1722 const MemSpaceRegion *MS = MR->getMemorySpace();
1724 if (isa<StackLocalsSpaceRegion>(MS)) {
1725 const VarRegion *VR = dyn_cast<VarRegion>(MR);
1733 os <<
"the address of the local variable '" << VD->
getName() <<
"'";
1735 os <<
"the address of a local stack variable";
1739 if (isa<StackArgumentsSpaceRegion>(MS)) {
1740 const VarRegion *VR = dyn_cast<VarRegion>(MR);
1748 os <<
"the address of the parameter '" << VD->
getName() <<
"'";
1750 os <<
"the address of a parameter";
1754 if (isa<GlobalsSpaceRegion>(MS)) {
1755 const VarRegion *VR = dyn_cast<VarRegion>(MR);
1763 if (VD->isStaticLocal())
1764 os <<
"the address of the static variable '" << VD->
getName() <<
"'";
1766 os <<
"the address of the global variable '" << VD->getName() <<
"'";
1768 os <<
"the address of a global variable";
1777 void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
1779 const Expr *DeallocExpr)
const {
1781 if (!ChecksEnabled[CK_MallocChecker] &&
1782 !ChecksEnabled[CK_NewDeleteChecker])
1786 getCheckIfTracked(C, DeallocExpr);
1787 if (!CheckKind.hasValue())
1790 if (ExplodedNode *N = C.generateErrorNode()) {
1791 if (!BT_BadFree[*CheckKind])
1792 BT_BadFree[*CheckKind].reset(
new BugType(
1796 llvm::raw_svector_ostream os(buf);
1798 const MemRegion *MR = ArgVal.getAsRegion();
1799 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1800 MR = ER->getSuperRegion();
1802 os <<
"Argument to ";
1803 if (!printAllocDeallocName(os, C, DeallocExpr))
1804 os <<
"deallocator";
1807 bool Summarized = MR ? SummarizeRegion(os, MR)
1808 : SummarizeValue(os, ArgVal);
1810 os <<
", which is not memory allocated by ";
1812 os <<
"not memory allocated by ";
1814 printExpectedAllocName(os, C, DeallocExpr);
1816 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
1817 R->markInteresting(MR);
1819 C.emitReport(std::move(R));
1823 void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
1828 if (ChecksEnabled[CK_MallocChecker])
1829 CheckKind = CK_MallocChecker;
1830 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
1831 CheckKind = CK_MismatchedDeallocatorChecker;
1835 if (ExplodedNode *N = C.generateErrorNode()) {
1836 if (!BT_FreeAlloca[*CheckKind])
1837 BT_FreeAlloca[*CheckKind].reset(
new BugType(
1840 auto R = llvm::make_unique<BugReport>(
1841 *BT_FreeAlloca[*CheckKind],
1842 "Memory allocated by alloca() should not be deallocated", N);
1843 R->markInteresting(ArgVal.getAsRegion());
1845 C.emitReport(std::move(R));
1849 void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
1851 const Expr *DeallocExpr,
1854 bool OwnershipTransferred)
const {
1856 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
1859 if (ExplodedNode *N = C.generateErrorNode()) {
1860 if (!BT_MismatchedDealloc)
1861 BT_MismatchedDealloc.reset(
1862 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
1866 llvm::raw_svector_ostream os(buf);
1868 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1870 llvm::raw_svector_ostream AllocOs(AllocBuf);
1872 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1874 if (OwnershipTransferred) {
1875 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1876 os << DeallocOs.str() <<
" cannot";
1880 os <<
" take ownership of memory";
1882 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1883 os <<
" allocated by " << AllocOs.str();
1886 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1887 os <<
" allocated by " << AllocOs.str();
1889 os <<
" should be deallocated by ";
1890 printExpectedDeallocName(os, RS->getAllocationFamily());
1892 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1893 os <<
", not " << DeallocOs.str();
1896 auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
1897 R->markInteresting(Sym);
1899 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1900 C.emitReport(std::move(R));
1904 void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
1906 const Expr *AllocExpr)
const {
1909 if (!ChecksEnabled[CK_MallocChecker] &&
1910 !ChecksEnabled[CK_NewDeleteChecker])
1914 getCheckIfTracked(C, AllocExpr);
1915 if (!CheckKind.hasValue())
1918 ExplodedNode *N = C.generateErrorNode();
1922 if (!BT_OffsetFree[*CheckKind])
1923 BT_OffsetFree[*CheckKind].reset(
new BugType(
1927 llvm::raw_svector_ostream os(buf);
1929 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1931 const MemRegion *MR = ArgVal.getAsRegion();
1932 assert(MR &&
"Only MemRegion based symbols can have offset free errors");
1934 RegionOffset
Offset = MR->getAsOffset();
1935 assert((Offset.isValid() &&
1936 !Offset.hasSymbolicOffset() &&
1937 Offset.getOffset() != 0) &&
1938 "Only symbols with a valid offset can have offset free errors");
1940 int offsetBytes = Offset.getOffset() / C.getASTContext().
getCharWidth();
1942 os <<
"Argument to ";
1943 if (!printAllocDeallocName(os, C, DeallocExpr))
1944 os <<
"deallocator";
1945 os <<
" is offset by " 1948 << ((
abs(offsetBytes) > 1) ?
"bytes" :
"byte")
1949 <<
" from the start of ";
1950 if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1951 os <<
"memory allocated by " << AllocNameOs.str();
1953 os <<
"allocated memory";
1955 auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
1956 R->markInteresting(MR->getBaseRegion());
1958 C.emitReport(std::move(R));
1961 void MallocChecker::ReportUseAfterFree(CheckerContext &C,
SourceRange Range,
1964 if (!ChecksEnabled[CK_MallocChecker] &&
1965 !ChecksEnabled[CK_NewDeleteChecker] &&
1966 !ChecksEnabled[CK_InnerPointerChecker])
1970 if (!CheckKind.hasValue())
1973 if (ExplodedNode *N = C.generateErrorNode()) {
1974 if (!BT_UseFree[*CheckKind])
1975 BT_UseFree[*CheckKind].reset(
new BugType(
1979 C.getState()->get<RegionState>(Sym)->getAllocationFamily();
1981 auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
1982 AF == AF_InnerBuffer
1983 ?
"Inner pointer of container used after re/deallocation" 1984 :
"Use of memory after it is freed",
1987 R->markInteresting(Sym);
1989 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1991 if (AF == AF_InnerBuffer)
1994 C.emitReport(std::move(R));
1998 void MallocChecker::ReportDoubleFree(CheckerContext &C,
SourceRange Range,
2002 if (!ChecksEnabled[CK_MallocChecker] &&
2003 !ChecksEnabled[CK_NewDeleteChecker])
2007 if (!CheckKind.hasValue())
2010 if (ExplodedNode *N = C.generateErrorNode()) {
2011 if (!BT_DoubleFree[*CheckKind])
2012 BT_DoubleFree[*CheckKind].reset(
new BugType(
2015 auto R = llvm::make_unique<BugReport>(
2016 *BT_DoubleFree[*CheckKind],
2017 (Released ?
"Attempt to free released memory" 2018 :
"Attempt to free non-owned memory"),
2021 R->markInteresting(Sym);
2023 R->markInteresting(PrevSym);
2024 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2025 C.emitReport(std::move(R));
2029 void MallocChecker::ReportDoubleDelete(CheckerContext &C,
SymbolRef Sym)
const {
2031 if (!ChecksEnabled[CK_NewDeleteChecker])
2035 if (!CheckKind.hasValue())
2038 if (ExplodedNode *N = C.generateErrorNode()) {
2039 if (!BT_DoubleDelete)
2040 BT_DoubleDelete.reset(
new BugType(CheckNames[CK_NewDeleteChecker],
2044 auto R = llvm::make_unique<BugReport>(
2045 *BT_DoubleDelete,
"Attempt to delete released memory", N);
2047 R->markInteresting(Sym);
2048 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2049 C.emitReport(std::move(R));
2053 void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
2057 if (!ChecksEnabled[CK_MallocChecker] &&
2058 !ChecksEnabled[CK_NewDeleteChecker])
2063 if (!CheckKind.hasValue())
2066 if (ExplodedNode *N = C.generateErrorNode()) {
2067 if (!BT_UseZerroAllocated[*CheckKind])
2068 BT_UseZerroAllocated[*CheckKind].reset(
2069 new BugType(CheckNames[*CheckKind],
"Use of zero allocated",
2072 auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
2073 "Use of zero-allocated memory", N);
2077 R->markInteresting(Sym);
2078 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
2080 C.emitReport(std::move(R));
2084 void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
2086 const Expr *FreeExpr)
const {
2087 if (!ChecksEnabled[CK_MallocChecker])
2091 if (!CheckKind.hasValue())
2094 if (ExplodedNode *N = C.generateErrorNode()) {
2095 if (!BT_BadFree[*CheckKind])
2096 BT_BadFree[*CheckKind].reset(
new BugType(
2100 llvm::raw_svector_ostream Os(Buf);
2102 const MemRegion *MR = ArgVal.getAsRegion();
2103 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2104 MR = ER->getSuperRegion();
2106 Os <<
"Argument to ";
2107 if (!printAllocDeallocName(Os, C, FreeExpr))
2108 Os <<
"deallocator";
2110 Os <<
" is a function pointer";
2112 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str(), N);
2113 R->markInteresting(MR);
2115 C.emitReport(std::move(R));
2123 bool SuffixWithN)
const {
2133 SVal Arg0Val = C.getSVal(arg0Expr);
2134 if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
2136 DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
2138 SValBuilder &svalBuilder = C.getSValBuilder();
2140 DefinedOrUnknownSVal PtrEQ =
2141 svalBuilder.evalEQ(
State, arg0Val, svalBuilder.makeNull());
2147 SVal TotalSize = C.getSVal(Arg1);
2149 TotalSize = evalMulForBufferSize(C, Arg1, CE->
getArg(2));
2150 if (!TotalSize.getAs<DefinedOrUnknownSVal>())
2154 DefinedOrUnknownSVal SizeZero =
2155 svalBuilder.evalEQ(
State, TotalSize.castAs<DefinedOrUnknownSVal>(),
2156 svalBuilder.makeIntValWithPtrWidth(0,
false));
2159 std::tie(StatePtrIsNull, StatePtrNotNull) =
State->assume(PtrEQ);
2161 std::tie(StateSizeIsZero, StateSizeNotZero) =
State->assume(SizeZero);
2164 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
2165 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
2169 if (PrtIsNull && !SizeIsZero) {
2171 UndefinedVal(), StatePtrIsNull);
2175 if (PrtIsNull && SizeIsZero)
2180 SymbolRef FromPtr = arg0Val.getAsSymbol();
2181 SVal RetVal = C.getSVal(CE);
2183 if (!FromPtr || !ToPtr)
2186 bool ReleasedAllocated =
false;
2191 false, ReleasedAllocated)){
2201 FreeMemAux(C, CE,
State, 0,
false, ReleasedAllocated)) {
2204 UnknownVal(), stateFree);
2210 Kind = RPIsFreeOnFailure;
2211 else if (!ReleasedAllocated)
2212 Kind = RPDoNotTrackAfterFailure;
2216 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
2217 ReallocPair(FromPtr, Kind));
2219 C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
2220 return stateRealloc;
2233 SValBuilder &svalBuilder = C.getSValBuilder();
2234 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
2235 SVal TotalSize = evalMulForBufferSize(C, CE->
getArg(0), CE->
getArg(1));
2237 return MallocMemAux(C, CE, TotalSize, zeroVal, State);
2241 MallocChecker::getAllocationSite(
const ExplodedNode *N,
SymbolRef Sym,
2242 CheckerContext &C)
const {
2246 const ExplodedNode *AllocNode = N;
2247 const MemRegion *ReferenceRegion =
nullptr;
2251 if (!State->get<RegionState>(Sym))
2256 if (!ReferenceRegion) {
2257 if (
const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
2258 SVal Val = State->getSVal(MR);
2259 if (Val.getAsLocSymbol() == Sym) {
2260 const VarRegion* VR = MR->getBaseRegion()->getAs<VarRegion>();
2265 ReferenceRegion = MR;
2273 if (NContext == LeakContext ||
2276 N = N->pred_empty() ? nullptr : *(N->pred_begin());
2279 return LeakInfo(AllocNode, ReferenceRegion);
2282 void MallocChecker::reportLeak(
SymbolRef Sym, ExplodedNode *N,
2283 CheckerContext &C)
const {
2285 if (!ChecksEnabled[CK_MallocChecker] &&
2286 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2289 const RefState *RS = C.getState()->get<RegionState>(Sym);
2290 assert(RS &&
"cannot leak an untracked symbol");
2293 if (Family == AF_Alloca)
2297 CheckKind = getCheckIfTracked(Family,
true);
2299 if (!CheckKind.hasValue())
2303 if (!BT_Leak[*CheckKind]) {
2304 BT_Leak[*CheckKind].reset(
new BugType(CheckNames[*CheckKind],
"Memory leak",
2311 BT_Leak[*CheckKind]->setSuppressOnSink(
true);
2317 PathDiagnosticLocation LocUsedForUniqueing;
2318 const ExplodedNode *AllocNode =
nullptr;
2319 const MemRegion *Region =
nullptr;
2320 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2325 C.getSourceManager(),
2326 AllocNode->getLocationContext());
2329 llvm::raw_svector_ostream os(buf);
2330 if (Region && Region->canPrintPretty()) {
2331 os <<
"Potential leak of memory pointed to by ";
2332 Region->printPretty(os);
2334 os <<
"Potential memory leak";
2337 auto R = llvm::make_unique<BugReport>(
2338 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2339 AllocNode->getLocationContext()->getDecl());
2340 R->markInteresting(Sym);
2341 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym,
true));
2342 C.emitReport(std::move(R));
2345 void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
2346 CheckerContext &C)
const 2349 RegionStateTy OldRS = state->get<RegionState>();
2350 RegionStateTy::Factory &F = state->get_context<RegionState>();
2352 RegionStateTy RS = OldRS;
2354 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2355 if (SymReaper.isDead(I->first)) {
2356 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2357 Errors.push_back(I->first);
2359 RS = F.remove(RS, I->first);
2365 assert(state->get<ReallocPairs>() ==
2366 C.getState()->get<ReallocPairs>());
2367 assert(state->get<FreeReturnValue>() ==
2368 C.getState()->get<FreeReturnValue>());
2373 ReallocPairsTy RP = state->get<ReallocPairs>();
2374 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2375 if (SymReaper.isDead(I->first) ||
2376 SymReaper.isDead(I->second.ReallocatedSym)) {
2377 state = state->remove<ReallocPairs>(I->first);
2382 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2383 for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
2384 if (SymReaper.isDead(I->first) ||
2385 SymReaper.isDead(I->second)) {
2386 state = state->remove<FreeReturnValue>(I->first);
2391 ExplodedNode *N = C.getPredecessor();
2392 if (!Errors.empty()) {
2393 static CheckerProgramPointTag Tag(
"MallocChecker",
"DeadSymbolsLeak");
2394 N = C.generateNonFatalErrorNode(C.getState(), &Tag);
2397 I = Errors.begin(), E = Errors.end(); I != E; ++I) {
2398 reportLeak(*I, N, C);
2403 C.addTransition(state->set<RegionState>(RS), N);
2406 void MallocChecker::checkPreCall(
const CallEvent &Call,
2407 CheckerContext &C)
const {
2410 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2411 if (!Sym || checkDoubleDelete(Sym, C))
2422 if (ChecksEnabled[CK_MallocChecker] &&
2423 (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
2424 isCMemFunction(FD, Ctx, AF_IfNameIndex,
2425 MemoryOperationKind::MOK_Free)))
2431 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2432 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2437 for (
unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
2438 SVal ArgSVal = Call.getArgSVal(I);
2439 if (ArgSVal.getAs<Loc>()) {
2443 if (checkUseAfterFree(Sym, C, Call.getArgExpr(I)))
2449 void MallocChecker::checkPreStmt(
const ReturnStmt *S,
2450 CheckerContext &C)
const {
2451 checkEscapeOnReturn(S, C);
2457 void MallocChecker::checkEndFunction(
const ReturnStmt *S,
2458 CheckerContext &C)
const {
2459 checkEscapeOnReturn(S, C);
2462 void MallocChecker::checkEscapeOnReturn(
const ReturnStmt *S,
2463 CheckerContext &C)
const {
2473 SVal RetVal = C.getSVal(E);
2479 if (
const MemRegion *MR = RetVal.getAsRegion())
2480 if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
2481 if (
const SymbolicRegion *BMR =
2482 dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
2483 Sym = BMR->getSymbol();
2487 checkUseAfterFree(Sym, C, E);
2493 void MallocChecker::checkPostStmt(
const BlockExpr *BE,
2494 CheckerContext &C)
const {
2502 const BlockDataRegion *R =
2503 cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
2505 BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
2506 E = R->referenced_vars_end();
2513 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
2515 for ( ; I != E; ++I) {
2516 const VarRegion *VR = I.getCapturedRegion();
2517 if (VR->getSuperRegion() == R) {
2518 VR = MemMgr.getVarRegion(VR->getDecl(), LC);
2520 Regions.push_back(VR);
2524 state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
2525 C.addTransition(state);
2528 bool MallocChecker::isReleased(
SymbolRef Sym, CheckerContext &C)
const {
2530 const RefState *RS = C.getState()->get<RegionState>(Sym);
2531 return (RS && RS->isReleased());
2534 bool MallocChecker::checkUseAfterFree(
SymbolRef Sym, CheckerContext &C,
2535 const Stmt *S)
const {
2537 if (isReleased(Sym, C)) {
2545 void MallocChecker::checkUseZeroAllocated(
SymbolRef Sym, CheckerContext &C,
2546 const Stmt *S)
const {
2549 if (
const RefState *RS = C.getState()->get<RegionState>(Sym)) {
2550 if (RS->isAllocatedOfSizeZero())
2551 ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
2553 else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
2558 bool MallocChecker::checkDoubleDelete(
SymbolRef Sym, CheckerContext &C)
const {
2560 if (isReleased(Sym, C)) {
2561 ReportDoubleDelete(C, Sym);
2568 void MallocChecker::checkLocation(SVal l,
bool isLoad,
const Stmt *S,
2569 CheckerContext &C)
const {
2572 checkUseAfterFree(Sym, C, S);
2573 checkUseZeroAllocated(Sym, C, S);
2581 bool Assumption)
const {
2582 RegionStateTy RS =
state->get<RegionState>();
2583 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2585 ConstraintManager &CMgr =
state->getConstraintManager();
2586 ConditionTruthVal AllocFailed = CMgr.isNull(
state, I.getKey());
2587 if (AllocFailed.isConstrainedTrue())
2588 state =
state->remove<RegionState>(I.getKey());
2593 ReallocPairsTy RP =
state->get<ReallocPairs>();
2594 for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
2596 ConstraintManager &CMgr =
state->getConstraintManager();
2597 ConditionTruthVal AllocFailed = CMgr.isNull(
state, I.getKey());
2598 if (!AllocFailed.isConstrainedTrue())
2601 SymbolRef ReallocSym = I.getData().ReallocatedSym;
2602 if (
const RefState *RS =
state->get<RegionState>(ReallocSym)) {
2603 if (RS->isReleased()) {
2604 if (I.getData().Kind == RPToBeFreedAfterFailure)
2606 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
2607 else if (I.getData().Kind == RPDoNotTrackAfterFailure)
2608 state =
state->remove<RegionState>(ReallocSym);
2610 assert(I.getData().Kind == RPIsFreeOnFailure);
2613 state = state->remove<ReallocPairs>(I.getKey());
2619 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
2624 EscapingSymbol =
nullptr;
2630 if (!(isa<SimpleFunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
2634 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
2637 if (!Call->isInSystemHeader() || Call->argumentsMayEscape())
2650 return *FreeWhenDone;
2656 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
2657 if (FirstSlot.endswith(
"NoCopy"))
2664 if (FirstSlot.startswith(
"addPointer") ||
2665 FirstSlot.startswith(
"insertPointer") ||
2666 FirstSlot.startswith(
"replacePointer") ||
2667 FirstSlot.equals(
"valueWithPointer")) {
2674 if (Msg->getMethodFamily() ==
OMF_init) {
2675 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
2685 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
2693 if (isMemFunction(FD, ASTC))
2697 if (!Call->isInSystemHeader())
2704 StringRef FName = II->
getName();
2708 if (FName.endswith(
"NoCopy")) {
2712 for (
unsigned i = 1; i < Call->getNumArgs(); ++i) {
2713 const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts();
2714 if (
const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
2715 StringRef DeallocatorName = DE->getFoundDecl()->getName();
2716 if (DeallocatorName ==
"kCFAllocatorNull")
2727 if (FName ==
"funopen")
2728 if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0))
2734 if (FName ==
"setbuf" || FName ==
"setbuffer" ||
2735 FName ==
"setlinebuf" || FName ==
"setvbuf") {
2736 if (Call->getNumArgs() >= 1) {
2737 const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
2738 if (
const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
2739 if (
const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
2740 if (D->getCanonicalDecl()->getName().find(
"std") != StringRef::npos)
2750 if (FName ==
"CGBitmapContextCreate" ||
2751 FName ==
"CGBitmapContextCreateWithData" ||
2752 FName ==
"CVPixelBufferCreateWithBytes" ||
2753 FName ==
"CVPixelBufferCreateWithPlanarBytes" ||
2754 FName ==
"OSAtomicEnqueue") {
2758 if (FName ==
"postEvent" &&
2763 if (FName ==
"postEvent" &&
2768 if (FName ==
"connectImpl" &&
2777 if (Call->argumentsMayEscape())
2790 return (RS->getAllocationFamily() == AF_CXXNewArray ||
2791 RS->getAllocationFamily() == AF_CXXNew);
2798 return checkPointerEscapeAux(
State, Escaped, Call, Kind, &
retTrue);
2805 return checkPointerEscapeAux(
State, Escaped, Call, Kind,
2813 bool(*CheckRefState)(
const RefState*))
const {
2818 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call,
State,
2824 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2829 if (EscapingSymbol && EscapingSymbol != sym)
2832 if (
const RefState *RS =
State->get<RegionState>(sym)) {
2833 if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
2834 CheckRefState(RS)) {
2836 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2845 ReallocPairsTy currMap = currState->get<ReallocPairs>();
2846 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2848 for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end();
2851 if (!currMap.lookup(sym))
2860 StringRef N = II->getName();
2861 if (N.contains_lower(
"ptr") || N.contains_lower(
"pointer")) {
2862 if (N.contains_lower(
"ref") || N.contains_lower(
"cnt") ||
2863 N.contains_lower(
"intrusive") || N.contains_lower(
"shared")) {
2871 std::shared_ptr<PathDiagnosticPiece> MallocChecker::MallocBugVisitor::VisitNode(
2872 const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
2877 const RefState *RS = state->get<RegionState>(Sym);
2878 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2883 if (!S && (!RS || RS->getAllocationFamily() != AF_InnerBuffer))
2895 if (ReleaseDestructorLC) {
2896 if (
const auto *AE = dyn_cast<AtomicExpr>(S)) {
2898 if (Op == AtomicExpr::AO__c11_atomic_fetch_add ||
2899 Op == AtomicExpr::AO__c11_atomic_fetch_sub) {
2900 if (ReleaseDestructorLC == CurrentLC ||
2901 ReleaseDestructorLC->
isParentOf(CurrentLC)) {
2902 BR.markInvalid(getTag(), S);
2913 StackHintGeneratorForSymbol *StackHint =
nullptr;
2915 llvm::raw_svector_ostream
OS(Buf);
2917 if (Mode == Normal) {
2918 if (isAllocated(RS, RSPrev, S)) {
2919 Msg =
"Memory is allocated";
2920 StackHint =
new StackHintGeneratorForSymbol(Sym,
2921 "Returned allocated memory");
2922 }
else if (isReleased(RS, RSPrev, S)) {
2923 const auto Family = RS->getAllocationFamily();
2928 case AF_CXXNewArray:
2929 case AF_IfNameIndex:
2930 Msg =
"Memory is released";
2931 StackHint =
new StackHintGeneratorForSymbol(Sym,
2932 "Returning; memory was released");
2934 case AF_InnerBuffer: {
2935 const MemRegion *ObjRegion =
2937 const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
2938 QualType ObjTy = TypedRegion->getValueType();
2939 OS <<
"Inner buffer of '" << ObjTy.getAsString() <<
"' ";
2942 OS <<
"deallocated by call to destructor";
2943 StackHint =
new StackHintGeneratorForSymbol(Sym,
2944 "Returning; inner buffer was deallocated");
2946 OS <<
"reallocated by call to '";
2947 const Stmt *S = RS->getStmt();
2948 if (
const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
2949 OS << MemCallE->getMethodDecl()->getNameAsString();
2950 }
else if (
const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
2951 OS << OpCallE->getDirectCallee()->getNameAsString();
2952 }
else if (
const auto *CallE = dyn_cast<CallExpr>(S)) {
2953 auto &CEMgr = BRC.getStateManager().getCallEventManager();
2954 CallEventRef<> Call = CEMgr.getSimpleCall(CallE, state, CurrentLC);
2955 const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl());
2956 OS << (D ? D->getNameAsString() :
"unknown");
2959 StackHint =
new StackHintGeneratorForSymbol(Sym,
2960 "Returning; inner buffer was reallocated");
2966 llvm_unreachable(
"Unhandled allocation family!");
2972 bool FoundAnyDestructor =
false;
2974 if (
const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
2979 BR.markInvalid(getTag(), DD);
2980 }
else if (!FoundAnyDestructor) {
2981 assert(!ReleaseDestructorLC &&
2982 "There can be only one release point!");
2988 ReleaseDestructorLC = LC->getStackFrame();
2994 FoundAnyDestructor =
true;
2998 }
else if (isRelinquished(RS, RSPrev, S)) {
2999 Msg =
"Memory ownership is transferred";
3000 StackHint =
new StackHintGeneratorForSymbol(Sym,
"");
3001 }
else if (isReallocFailedCheck(RS, RSPrev, S)) {
3002 Mode = ReallocationFailed;
3003 Msg =
"Reallocation failed";
3004 StackHint =
new StackHintGeneratorForReallocationFailed(Sym,
3005 "Reallocation failed");
3009 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
3010 "We only support one failed realloc at a time.");
3011 BR.markInteresting(sym);
3012 FailedReallocSymbol = sym;
3017 }
else if (Mode == ReallocationFailed) {
3018 assert(FailedReallocSymbol &&
"No symbol to look for.");
3021 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
3023 Msg =
"Attempt to reallocate memory";
3024 StackHint =
new StackHintGeneratorForSymbol(Sym,
3025 "Returned reallocated memory");
3026 FailedReallocSymbol =
nullptr;
3036 PathDiagnosticLocation Pos;
3038 assert(RS->getAllocationFamily() == AF_InnerBuffer);
3042 Pos = PathDiagnosticLocation(PostImplCall->getLocation(),
3043 BRC.getSourceManager());
3045 Pos = PathDiagnosticLocation(S, BRC.getSourceManager(),
3046 N->getLocationContext());
3049 return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg,
true, StackHint);
3053 const char *NL,
const char *Sep)
const {
3055 RegionStateTy RS =
State->get<RegionState>();
3057 if (!RS.isEmpty()) {
3058 Out << Sep <<
"MallocChecker :" << NL;
3059 for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
3060 const RefState *RefS =
State->get<RegionState>(I.getKey());
3063 if (!CheckKind.hasValue())
3064 CheckKind = getCheckIfTracked(Family,
true);
3066 I.getKey()->dumpToStream(Out);
3068 I.getData().dump(Out);
3069 if (CheckKind.hasValue())
3070 Out <<
" (" << CheckNames[*CheckKind].
getName() <<
")";
3078 namespace allocation_state {
3083 return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
3094 "Optimistic",
false, checker);
3095 checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] =
true;
3096 checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
3100 if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
3101 checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] =
true;
3104 checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
3115 "Optimistic",
false, checker);
3116 checker->ChecksEnabled[MallocChecker::CK_InnerPointerChecker] =
true;
3117 checker->CheckNames[MallocChecker::CK_InnerPointerChecker] =
3121 #define REGISTER_CHECKER(name) \ 3122 void ento::register##name(CheckerManager &mgr) { \ 3123 registerCStringCheckerBasic(mgr); \ 3124 MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \ 3125 checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( \ 3126 "Optimistic", false, checker); \ 3127 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \ 3128 checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
const BlockDecl * getBlockDecl() const
Represents a function declaration or definition.
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
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...
bool operator==(CanQual< T > x, CanQual< U > y)
llvm::DenseSet< SymbolRef > InvalidatedSymbols
const SymExpr * SymbolRef
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
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.
void registerInnerPointerCheckerAux(CheckerManager &Mgr)
Register the part of MallocChecker connected to InnerPointerChecker.
__DEVICE__ long long abs(long long __n)
FunctionDecl * getOperatorNew() const
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const MemRegion * getContainerObjRegion(ProgramStateRef State, SymbolRef Sym)
'Sym' represents a pointer to the inner buffer of a container object.
Represents a call to a C++ constructor.
const TargetInfo & getTargetInfo() const
constexpr XRayInstrMask Function
Represents a C++ constructor within a class.
bool isConsumedExpr(Expr *E) const
Represents a variable declaration or definition.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
bool isParentOf(const LocationContext *LC) const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call)
One of these records is kept for each identifier that is lexed.
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 CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
std::unique_ptr< BugReporterVisitor > getInnerPointerBRVisitor(SymbolRef Sym)
This function provides an additional visitor that augments the bug report with information relevant t...
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
bool getCheckerBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C, bool SearchInParents=false) const
Interprets an option's string value as a boolean.
ArrayRef< ParmVarDecl * > parameters() const
static bool isLocType(QualType T)
void registerCStringCheckerBasic(CheckerManager &Mgr)
Register the checker which evaluates CString API calls.
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 * getParent() const
static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD)
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...
CheckName getCurrentCheckName() const
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
Represents an implicit call to a C++ destructor.
static bool retTrue(const RefState *RS)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Represents a C++ destructor within a class.
The pointer has been passed to a function call directly.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
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.
unsigned getNumArgs() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
ASTContext & getASTContext() const LLVM_READONLY
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
QualType getAllocatedType() const
static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState)
static bool treatUnusedNewEscaped(const CXXNewExpr *NE)
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
Selector getSelector() const
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
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.
static QualType getDeepPointeeType(QualType T)
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
AnalyzerOptions & getAnalyzerOptions()
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
#define REGISTER_CHECKER(name)
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)
const StackFrameContext * getStackFrame() const
ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin)
SourceManager & getSourceManager()
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
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
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.
std::string getQualifiedNameAsString() const
A reference to a declared variable, function, enum, etc.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
SourceLocation getLocation() const