29 #include "llvm/ADT/ImmutableMap.h"
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/SmallString.h"
32 #include "llvm/ADT/StringExtras.h"
35 using namespace clang;
71 RefState(
Kind k,
const Stmt *s,
unsigned family)
72 :
S(s), K(k), Family(family) {
73 assert(family != AF_None);
76 bool isAllocated()
const {
return K == Allocated; }
77 bool isAllocatedOfSizeZero()
const {
return K == AllocatedOfSizeZero; }
78 bool isReleased()
const {
return K == Released; }
79 bool isRelinquished()
const {
return K == Relinquished; }
80 bool isEscaped()
const {
return K == Escaped; }
84 const Stmt *getStmt()
const {
return S; }
87 return K == X.K &&
S == X.S && Family == X.Family;
90 static RefState getAllocated(
unsigned family,
const Stmt *s) {
91 return RefState(Allocated, s, family);
93 static RefState getAllocatedOfSizeZero(
const RefState *RS) {
94 return RefState(AllocatedOfSizeZero, RS->getStmt(),
95 RS->getAllocationFamily());
97 static RefState getReleased(
unsigned family,
const Stmt *s) {
98 return RefState(Released, s, family);
100 static RefState getRelinquished(
unsigned family,
const Stmt *s) {
101 return RefState(Relinquished, s, family);
103 static RefState getEscaped(
const RefState *RS) {
104 return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
107 void Profile(llvm::FoldingSetNodeID &
ID)
const {
110 ID.AddInteger(Family);
113 void dump(raw_ostream &OS)
const {
114 switch (static_cast<Kind>(K)) {
115 #define CASE(ID) case ID: OS << #ID; break;
117 CASE(AllocatedOfSizeZero)
124 LLVM_DUMP_METHOD
void dump()
const {
dump(llvm::errs()); }
128 RPToBeFreedAfterFailure,
132 RPDoNotTrackAfterFailure
144 ReallocatedSym(S),
Kind(K) {}
145 void Profile(llvm::FoldingSetNodeID &ID)
const {
147 ID.AddPointer(ReallocatedSym);
150 return ReallocatedSym == X.ReallocatedSym &&
155 typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo;
157 class MallocChecker :
public Checker<check::DeadSymbols,
158 check::PointerEscape,
159 check::ConstPointerEscape,
160 check::PreStmt<ReturnStmt>,
162 check::PostStmt<CallExpr>,
163 check::PostStmt<CXXNewExpr>,
164 check::PreStmt<CXXDeleteExpr>,
165 check::PostStmt<BlockExpr>,
166 check::PostObjCMessage,
172 : II_alloca(nullptr), II_malloc(nullptr), II_free(nullptr),
173 II_realloc(nullptr), II_calloc(nullptr), II_valloc(nullptr),
174 II_reallocf(nullptr), II_strndup(nullptr), II_strdup(nullptr),
175 II_kmalloc(nullptr), II_if_nameindex(nullptr),
176 II_if_freenameindex(nullptr) {}
183 CK_NewDeleteLeaksChecker,
184 CK_MismatchedDeallocatorChecker,
188 enum class MemoryOperationKind {
208 bool Assumption)
const;
209 void checkLocation(
SVal l,
bool isLoad,
const Stmt *
S,
222 const char *NL,
const char *Sep)
const override;
225 mutable std::unique_ptr<BugType> BT_DoubleFree[CK_NumCheckKinds];
226 mutable std::unique_ptr<BugType> BT_DoubleDelete;
227 mutable std::unique_ptr<BugType> BT_Leak[CK_NumCheckKinds];
228 mutable std::unique_ptr<BugType> BT_UseFree[CK_NumCheckKinds];
229 mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
230 mutable std::unique_ptr<BugType> BT_FreeAlloca[CK_NumCheckKinds];
231 mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
232 mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
233 mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
234 mutable IdentifierInfo *II_alloca, *II_malloc, *II_free, *II_realloc,
235 *II_calloc, *II_valloc, *II_reallocf, *II_strndup,
236 *II_strdup, *II_kmalloc, *II_if_nameindex,
237 *II_if_freenameindex;
238 mutable Optional<uint64_t> KernelZeroFlagVal;
249 const Expr *
E)
const;
254 const Expr *DeallocExpr)
const;
257 void printExpectedDeallocName(raw_ostream &os,
AllocationFamily Family)
const;
266 MemoryOperationKind MemKind)
const;
272 const unsigned AllocationSizeArg,
277 const OwnershipAttr* Att,
300 const OwnershipAttr* Att,
305 bool &ReleasedAllocated,
306 bool ReturnsNullOnFailure =
false)
const;
308 const Expr *ParentExpr,
311 bool &ReleasedAllocated,
312 bool ReturnsNullOnFailure =
false)
const;
315 bool FreesMemOnFailure,
326 const Stmt *
S)
const;
340 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
const CallEvent *Call,
349 bool(*CheckRefState)(
const RefState*))
const;
356 bool IsALeakCheck =
false)
const;
358 const Stmt *AllocDeallocStmt,
359 bool IsALeakCheck =
false)
const;
361 bool IsALeakCheck =
false)
const;
363 static bool SummarizeValue(raw_ostream &os,
SVal V);
364 static bool SummarizeRegion(raw_ostream &os,
const MemRegion *MR);
366 const Expr *DeallocExpr)
const;
370 const Expr *DeallocExpr,
const RefState *RS,
371 SymbolRef Sym,
bool OwnershipTransferred)
const;
373 const Expr *DeallocExpr,
374 const Expr *AllocExpr =
nullptr)
const;
395 class MallocBugVisitor final
398 enum NotificationMode {
407 NotificationMode Mode;
415 MallocBugVisitor(
SymbolRef S,
bool isLeak =
false)
416 : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr), IsLeak(isLeak) {}
418 void Profile(llvm::FoldingSetNodeID &ID)
const override {
424 inline bool isAllocated(
const RefState *
S,
const RefState *SPrev,
427 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
428 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
429 (!SPrev || !(SPrev->isAllocated() ||
430 SPrev->isAllocatedOfSizeZero())));
433 inline bool isReleased(
const RefState *S,
const RefState *SPrev,
436 return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) &&
437 (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
440 inline bool isRelinquished(
const RefState *S,
const RefState *SPrev,
443 return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
444 isa<ObjCPropertyRefExpr>(Stmt)) &&
445 (S && S->isRelinquished()) &&
446 (!SPrev || !SPrev->isRelinquished()));
449 inline bool isReallocFailedCheck(
const RefState *S,
const RefState *SPrev,
455 return ((!Stmt || !isa<CallExpr>(Stmt)) &&
456 (S && (S->isAllocated() || S->isAllocatedOfSizeZero())) &&
457 (SPrev && !(SPrev->isAllocated() ||
458 SPrev->isAllocatedOfSizeZero())));
466 std::unique_ptr<PathDiagnosticPiece>
476 return llvm::make_unique<PathDiagnosticEventPiece>(L, BR.
getDescription(),
481 class StackHintGeneratorForReallocationFailed
484 StackHintGeneratorForReallocationFailed(
SymbolRef S, StringRef M)
487 std::string getMessageForArg(
const Expr *ArgE,
488 unsigned ArgIndex)
override {
493 llvm::raw_svector_ostream os(buf);
495 os <<
"Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
496 <<
" parameter failed";
502 return "Reallocation of returned value failed";
524 bool VisitSymbol(SymbolRef sym)
override {
525 state = state->remove<RegionState>(sym);
531 void MallocChecker::initIdentifierInfo(
ASTContext &Ctx)
const {
538 II_reallocf = &Ctx.
Idents.
get(
"reallocf");
544 II_if_nameindex = &Ctx.
Idents.
get(
"if_nameindex");
545 II_if_freenameindex = &Ctx.
Idents.
get(
"if_freenameindex");
549 if (isCMemFunction(FD, C, AF_Malloc, MemoryOperationKind::MOK_Any))
552 if (isCMemFunction(FD, C, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
555 if (isCMemFunction(FD, C, AF_Alloca, MemoryOperationKind::MOK_Any))
558 if (isStandardNewDelete(FD, C))
564 bool MallocChecker::isCMemFunction(
const FunctionDecl *FD,
567 MemoryOperationKind MemKind)
const {
571 bool CheckFree = (MemKind == MemoryOperationKind::MOK_Any ||
572 MemKind == MemoryOperationKind::MOK_Free);
573 bool CheckAlloc = (MemKind == MemoryOperationKind::MOK_Any ||
574 MemKind == MemoryOperationKind::MOK_Allocate);
576 if (FD->
getKind() == Decl::Function) {
578 initIdentifierInfo(C);
580 if (Family == AF_Malloc && CheckFree) {
581 if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
585 if (Family == AF_Malloc && CheckAlloc) {
586 if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
587 FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
588 FunI == II_strndup || FunI == II_kmalloc)
592 if (Family == AF_IfNameIndex && CheckFree) {
593 if (FunI == II_if_freenameindex)
597 if (Family == AF_IfNameIndex && CheckAlloc) {
598 if (FunI == II_if_nameindex)
602 if (Family == AF_Alloca && CheckAlloc) {
603 if (FunI == II_alloca)
608 if (Family != AF_Malloc)
611 if (IsOptimistic && FD->
hasAttrs()) {
613 OwnershipAttr::OwnershipKind OwnKind =
I->getOwnKind();
614 if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
617 }
else if (OwnKind == OwnershipAttr::Returns) {
631 bool MallocChecker::isStandardNewDelete(
const FunctionDecl *FD,
637 if (Kind != OO_New && Kind != OO_Array_New &&
638 Kind != OO_Delete && Kind != OO_Array_Delete)
642 if (isa<CXXMethodDecl>(FD))
649 return II->getName().equals(
"nothrow_t");
681 if (!KernelZeroFlagVal.hasValue()) {
682 if (OS == llvm::Triple::FreeBSD)
683 KernelZeroFlagVal = 0x0100;
684 else if (OS == llvm::Triple::NetBSD)
685 KernelZeroFlagVal = 0x0002;
686 else if (OS == llvm::Triple::OpenBSD)
687 KernelZeroFlagVal = 0x0008;
688 else if (OS == llvm::Triple::Linux)
690 KernelZeroFlagVal = 0x8000;
727 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
730 if (TrueState && !FalseState) {
732 return MallocMemAux(C, CE, CE->
getArg(0), ZeroVal, TrueState);
747 bool ReleasedAllocatedMemory =
false;
749 if (FD->
getKind() == Decl::Function) {
753 if (FunI == II_malloc) {
759 State = ProcessZeroAllocation(C, CE, 0, State);
762 performKernelMalloc(CE, C, State);
763 if (MaybeState.hasValue())
764 State = MaybeState.getValue();
768 }
else if (FunI == II_kmalloc) {
770 performKernelMalloc(CE, C, State);
771 if (MaybeState.hasValue())
772 State = MaybeState.getValue();
775 }
else if (FunI == II_valloc) {
779 State = ProcessZeroAllocation(C, CE, 0, State);
780 }
else if (FunI == II_realloc) {
781 State = ReallocMem(C, CE,
false, State);
782 State = ProcessZeroAllocation(C, CE, 1, State);
783 }
else if (FunI == II_reallocf) {
784 State = ReallocMem(C, CE,
true, State);
785 State = ProcessZeroAllocation(C, CE, 1, State);
786 }
else if (FunI == II_calloc) {
787 State = CallocMem(C, CE, State);
788 State = ProcessZeroAllocation(C, CE, 0, State);
789 State = ProcessZeroAllocation(C, CE, 1, State);
790 }
else if (FunI == II_free) {
791 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
792 }
else if (FunI == II_strdup) {
793 State = MallocUpdateRefState(C, CE, State);
794 }
else if (FunI == II_strndup) {
795 State = MallocUpdateRefState(C, CE, State);
796 }
else if (FunI == II_alloca) {
799 State = ProcessZeroAllocation(C, CE, 0, State);
809 State = ProcessZeroAllocation(C, CE, 0, State);
811 else if (K == OO_Array_New) {
814 State = ProcessZeroAllocation(C, CE, 0, State);
816 else if (K == OO_Delete || K == OO_Array_Delete)
817 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
819 llvm_unreachable(
"not a new/delete operator");
820 }
else if (FunI == II_if_nameindex) {
825 }
else if (FunI == II_if_freenameindex) {
826 State = FreeMemAux(C, CE, State, 0,
false, ReleasedAllocatedMemory);
830 if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
835 switch (
I->getOwnKind()) {
836 case OwnershipAttr::Returns:
837 State = MallocMemReturnsAttr(C, CE,
I, State);
839 case OwnershipAttr::Takes:
840 case OwnershipAttr::Holds:
841 State = FreeMemAttr(C, CE,
I, State);
852 const unsigned AllocationSizeArg,
857 const Expr *Arg =
nullptr;
859 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
860 Arg = CE->
getArg(AllocationSizeArg);
862 else if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
864 Arg = NE->getArraySize();
869 llvm_unreachable(
"not a CallExpr or CXXNewExpr");
873 Optional<DefinedSVal> DefArgVal =
885 std::tie(TrueState, FalseState) =
886 State->assume(SvalBuilder.
evalEQ(State, *DefArgVal, Zero));
888 if (TrueState && !FalseState) {
894 const RefState *RS = State->get<RegionState>(Sym);
896 if (RS->isAllocated())
897 return TrueState->set<RegionState>(Sym,
898 RefState::getAllocatedOfSizeZero(RS));
906 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
917 while (!PointeeType.isNull()) {
918 Result = PointeeType;
936 for (
const auto *CtorParam : CtorD->
params()) {
939 if (CtorParamPointeeT.
isNull())
951 void MallocChecker::checkPostStmt(
const CXXNewExpr *NE,
958 checkUseAfterFree(Sym, C, *
I);
972 State = MallocUpdateRefState(C, NE, State, NE->
isArray() ? AF_CXXNewArray
974 State = ProcessZeroAllocation(C, NE, 0, State);
981 if (!ChecksEnabled[CK_NewDeleteChecker])
989 bool ReleasedAllocated;
991 false, ReleasedAllocated);
1003 return FirstSlot ==
"dataWithBytesNoCopy" ||
1004 FirstSlot ==
"initWithBytesNoCopy" ||
1005 FirstSlot ==
"initWithCharactersNoCopy";
1012 for (
unsigned i = 1; i < S.
getNumArgs(); ++i)
1014 return !Call.getArgSVal(i).isZeroConstant();
1019 void MallocChecker::checkPostObjCMessage(
const ObjCMethodCall &Call,
1031 bool ReleasedAllocatedMemory;
1034 true, ReleasedAllocatedMemory,
1042 const OwnershipAttr *Att,
1047 if (Att->getModule() != II_malloc)
1050 OwnershipAttr::args_iterator
I = Att->args_begin(), E = Att->args_end();
1066 Init, State, Family);
1092 State = State->bindDefault(RetVal, Init);
1096 dyn_cast_or_null<SymbolicRegion>(RetVal.
getAsRegion());
1099 if (Optional<DefinedOrUnknownSVal> DefinedSize =
1104 svalBuilder.
evalEQ(State, Extent, *DefinedSize);
1106 State = State->assume(extentMatchesSize,
true);
1110 return MallocUpdateRefState(C, CE, State, Family);
1131 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
1136 const OwnershipAttr *Att,
1141 if (Att->getModule() != II_malloc)
1144 bool ReleasedAllocated =
false;
1146 for (
const auto &Arg : Att->args()) {
1148 Att->getOwnKind() == OwnershipAttr::Holds,
1161 bool &ReleasedAllocated,
1162 bool ReturnsNullOnFailure)
const {
1169 return FreeMemAux(C, CE->
getArg(Num), CE,
State, Hold,
1170 ReleasedAllocated, ReturnsNullOnFailure);
1177 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
1179 assert(*Ret &&
"We should not store the null return symbol");
1182 RetStatusSymbol = *Ret;
1189 const Stmt *S)
const {
1193 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1201 if (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Any))
1204 if (isStandardNewDelete(FD, Ctx)) {
1206 if (Kind == OO_New || Kind == OO_Delete)
1208 else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
1209 return AF_CXXNewArray;
1212 if (isCMemFunction(FD, Ctx, AF_IfNameIndex, MemoryOperationKind::MOK_Any))
1213 return AF_IfNameIndex;
1215 if (isCMemFunction(FD, Ctx, AF_Alloca, MemoryOperationKind::MOK_Any))
1221 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
1222 return NE->
isArray() ? AF_CXXNewArray : AF_CXXNew;
1225 return DE->
isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
1227 if (isa<ObjCMessageExpr>(S))
1233 bool MallocChecker::printAllocDeallocName(raw_ostream &os,
CheckerContext &C,
1234 const Expr *E)
const {
1235 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
1242 if (!FD->isOverloadedOperator())
1248 if (Msg->isInstanceMessage())
1252 Msg->getSelector().
print(os);
1256 if (
const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
1273 void MallocChecker::printExpectedAllocName(raw_ostream &os,
CheckerContext &C,
1274 const Expr *E)
const {
1278 case AF_Malloc: os <<
"malloc()";
return;
1279 case AF_CXXNew: os <<
"'new'";
return;
1280 case AF_CXXNewArray: os <<
"'new[]'";
return;
1281 case AF_IfNameIndex: os <<
"'if_nameindex()'";
return;
1283 case AF_None: llvm_unreachable(
"not a deallocation expression");
1287 void MallocChecker::printExpectedDeallocName(raw_ostream &os,
1290 case AF_Malloc: os <<
"free()";
return;
1291 case AF_CXXNew: os <<
"'delete'";
return;
1292 case AF_CXXNewArray: os <<
"'delete[]'";
return;
1293 case AF_IfNameIndex: os <<
"'if_freenameindex()'";
return;
1295 case AF_None: llvm_unreachable(
"suspicious argument");
1300 const Expr *ArgExpr,
1301 const Expr *ParentExpr,
1304 bool &ReleasedAllocated,
1305 bool ReturnsNullOnFailure)
const {
1321 std::tie(notNullState, nullState) = State->assume(location);
1322 if (nullState && !notNullState)
1335 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1342 if (isa<BlockDataRegion>(R)) {
1343 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1351 if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1360 if (isa<AllocaRegion>(R))
1361 ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1363 ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1375 const RefState *RsBase = State->get<RegionState>(SymBase);
1376 SymbolRef PreviousRetStatusSymbol =
nullptr;
1381 if (RsBase->getAllocationFamily() == AF_Alloca) {
1382 ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
1387 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1389 ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
1390 SymBase, PreviousRetStatusSymbol);
1395 }
else if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
1396 RsBase->isEscaped()) {
1399 bool DeallocMatchesAlloc =
1400 RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1401 if (!DeallocMatchesAlloc) {
1402 ReportMismatchedDealloc(C, ArgExpr->getSourceRange(),
1403 ParentExpr, RsBase, SymBase, Hold);
1413 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1414 ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1421 ReleasedAllocated = (RsBase !=
nullptr) && (RsBase->isAllocated() ||
1422 RsBase->isAllocatedOfSizeZero());
1425 State = State->remove<FreeReturnValue>(SymBase);
1429 if (ReturnsNullOnFailure) {
1432 if (RetStatusSymbol) {
1434 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1439 : getAllocationFamily(C, ParentExpr);
1442 return State->set<RegionState>(SymBase,
1443 RefState::getRelinquished(Family,
1446 return State->set<RegionState>(SymBase,
1447 RefState::getReleased(Family, ParentExpr));
1450 Optional<MallocChecker::CheckKind>
1452 bool IsALeakCheck)
const {
1456 case AF_IfNameIndex: {
1457 if (ChecksEnabled[CK_MallocChecker])
1458 return CK_MallocChecker;
1460 return Optional<MallocChecker::CheckKind>();
1463 case AF_CXXNewArray: {
1465 if (ChecksEnabled[CK_NewDeleteLeaksChecker])
1466 return CK_NewDeleteLeaksChecker;
1469 if (ChecksEnabled[CK_NewDeleteChecker])
1470 return CK_NewDeleteChecker;
1472 return Optional<MallocChecker::CheckKind>();
1475 llvm_unreachable(
"no family");
1478 llvm_unreachable(
"unhandled family");
1481 Optional<MallocChecker::CheckKind>
1483 const Stmt *AllocDeallocStmt,
1484 bool IsALeakCheck)
const {
1485 return getCheckIfTracked(getAllocationFamily(C, AllocDeallocStmt),
1489 Optional<MallocChecker::CheckKind>
1491 bool IsALeakCheck)
const {
1492 if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym))
1493 return CK_MallocChecker;
1495 const RefState *RS = C.
getState()->get<RegionState>(Sym);
1497 return getCheckIfTracked(RS->getAllocationFamily(), IsALeakCheck);
1500 bool MallocChecker::SummarizeValue(raw_ostream &os,
SVal V) {
1502 os <<
"an integer (" << IntVal->getValue() <<
")";
1504 os <<
"a constant address (" << ConstAddr->getValue() <<
")";
1506 os <<
"the address of the label '" << Label->getLabel()->getName() <<
"'";
1513 bool MallocChecker::SummarizeRegion(raw_ostream &os,
1517 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
1519 os <<
"the address of the function '" << *FD <<
'\'';
1521 os <<
"the address of a function";
1534 if (isa<StackLocalsSpaceRegion>(MS)) {
1543 os <<
"the address of the local variable '" << VD->
getName() <<
"'";
1545 os <<
"the address of a local stack variable";
1549 if (isa<StackArgumentsSpaceRegion>(MS)) {
1558 os <<
"the address of the parameter '" << VD->
getName() <<
"'";
1560 os <<
"the address of a parameter";
1564 if (isa<GlobalsSpaceRegion>(MS)) {
1573 if (VD->isStaticLocal())
1574 os <<
"the address of the static variable '" << VD->
getName() <<
"'";
1576 os <<
"the address of the global variable '" << VD->getName() <<
"'";
1578 os <<
"the address of a global variable";
1589 const Expr *DeallocExpr)
const {
1591 if (!ChecksEnabled[CK_MallocChecker] &&
1592 !ChecksEnabled[CK_NewDeleteChecker])
1595 Optional<MallocChecker::CheckKind> CheckKind =
1596 getCheckIfTracked(C, DeallocExpr);
1597 if (!CheckKind.hasValue())
1601 if (!BT_BadFree[*CheckKind])
1602 BT_BadFree[*CheckKind].reset(
1603 new BugType(CheckNames[*CheckKind],
"Bad free",
"Memory Error"));
1606 llvm::raw_svector_ostream os(buf);
1609 while (
const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1610 MR = ER->getSuperRegion();
1612 os <<
"Argument to ";
1613 if (!printAllocDeallocName(os, C, DeallocExpr))
1614 os <<
"deallocator";
1617 bool Summarized = MR ? SummarizeRegion(os, MR)
1618 : SummarizeValue(os, ArgVal);
1620 os <<
", which is not memory allocated by ";
1622 os <<
"not memory allocated by ";
1624 printExpectedAllocName(os, C, DeallocExpr);
1626 auto R = llvm::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
1627 R->markInteresting(MR);
1636 Optional<MallocChecker::CheckKind> CheckKind;
1638 if (ChecksEnabled[CK_MallocChecker])
1639 CheckKind = CK_MallocChecker;
1640 else if (ChecksEnabled[CK_MismatchedDeallocatorChecker])
1641 CheckKind = CK_MismatchedDeallocatorChecker;
1646 if (!BT_FreeAlloca[*CheckKind])
1647 BT_FreeAlloca[*CheckKind].reset(
1648 new BugType(CheckNames[*CheckKind],
"Free alloca()",
"Memory Error"));
1650 auto R = llvm::make_unique<BugReport>(
1651 *BT_FreeAlloca[*CheckKind],
1652 "Memory allocated by alloca() should not be deallocated", N);
1661 const Expr *DeallocExpr,
1664 bool OwnershipTransferred)
const {
1666 if (!ChecksEnabled[CK_MismatchedDeallocatorChecker])
1670 if (!BT_MismatchedDealloc)
1671 BT_MismatchedDealloc.reset(
1672 new BugType(CheckNames[CK_MismatchedDeallocatorChecker],
1673 "Bad deallocator",
"Memory Error"));
1676 llvm::raw_svector_ostream os(buf);
1678 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1680 llvm::raw_svector_ostream AllocOs(AllocBuf);
1682 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1684 if (OwnershipTransferred) {
1685 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1686 os << DeallocOs.str() <<
" cannot";
1690 os <<
" take ownership of memory";
1692 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1693 os <<
" allocated by " << AllocOs.str();
1696 if (printAllocDeallocName(AllocOs, C, AllocExpr))
1697 os <<
" allocated by " << AllocOs.str();
1699 os <<
" should be deallocated by ";
1700 printExpectedDeallocName(os, RS->getAllocationFamily());
1702 if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1703 os <<
", not " << DeallocOs.str();
1706 auto R = llvm::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
1707 R->markInteresting(Sym);
1709 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1716 const Expr *AllocExpr)
const {
1719 if (!ChecksEnabled[CK_MallocChecker] &&
1720 !ChecksEnabled[CK_NewDeleteChecker])
1723 Optional<MallocChecker::CheckKind> CheckKind =
1724 getCheckIfTracked(C, AllocExpr);
1725 if (!CheckKind.hasValue())
1732 if (!BT_OffsetFree[*CheckKind])
1733 BT_OffsetFree[*CheckKind].reset(
1734 new BugType(CheckNames[*CheckKind],
"Offset free",
"Memory Error"));
1737 llvm::raw_svector_ostream os(buf);
1739 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1742 assert(MR &&
"Only MemRegion based symbols can have offset free errors");
1748 "Only symbols with a valid offset can have offset free errors");
1752 os <<
"Argument to ";
1753 if (!printAllocDeallocName(os, C, DeallocExpr))
1754 os <<
"deallocator";
1755 os <<
" is offset by "
1758 << ((abs(offsetBytes) > 1) ?
"bytes" :
"byte")
1759 <<
" from the start of ";
1760 if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1761 os <<
"memory allocated by " << AllocNameOs.str();
1763 os <<
"allocated memory";
1765 auto R = llvm::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
1774 if (!ChecksEnabled[CK_MallocChecker] &&
1775 !ChecksEnabled[CK_NewDeleteChecker])
1778 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1779 if (!CheckKind.hasValue())
1783 if (!BT_UseFree[*CheckKind])
1784 BT_UseFree[*CheckKind].reset(
new BugType(
1785 CheckNames[*CheckKind],
"Use-after-free",
"Memory Error"));
1787 auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
1788 "Use of memory after it is freed", N);
1790 R->markInteresting(Sym);
1792 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1801 if (!ChecksEnabled[CK_MallocChecker] &&
1802 !ChecksEnabled[CK_NewDeleteChecker])
1805 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1806 if (!CheckKind.hasValue())
1810 if (!BT_DoubleFree[*CheckKind])
1811 BT_DoubleFree[*CheckKind].reset(
1812 new BugType(CheckNames[*CheckKind],
"Double free",
"Memory Error"));
1814 auto R = llvm::make_unique<BugReport>(
1815 *BT_DoubleFree[*CheckKind],
1816 (Released ?
"Attempt to free released memory"
1817 :
"Attempt to free non-owned memory"),
1820 R->markInteresting(Sym);
1822 R->markInteresting(PrevSym);
1823 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1830 if (!ChecksEnabled[CK_NewDeleteChecker])
1833 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1834 if (!CheckKind.hasValue())
1838 if (!BT_DoubleDelete)
1839 BT_DoubleDelete.reset(
new BugType(CheckNames[CK_NewDeleteChecker],
1840 "Double delete",
"Memory Error"));
1842 auto R = llvm::make_unique<BugReport>(
1843 *BT_DoubleDelete,
"Attempt to delete released memory", N);
1845 R->markInteresting(Sym);
1846 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1855 if (!ChecksEnabled[CK_MallocChecker] &&
1856 !ChecksEnabled[CK_NewDeleteChecker])
1859 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(C, Sym);
1861 if (!CheckKind.hasValue())
1865 if (!BT_UseZerroAllocated[*CheckKind])
1866 BT_UseZerroAllocated[*CheckKind].reset(
new BugType(
1867 CheckNames[*CheckKind],
"Use of zero allocated",
"Memory Error"));
1869 auto R = llvm::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
1870 "Use of zero-allocated memory", N);
1874 R->markInteresting(Sym);
1875 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
1893 SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
1901 svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
1909 SVal Arg1ValG = State->getSVal(Arg1, LCtx);
1916 svalBuilder.evalEQ(State, Arg1Val,
1917 svalBuilder.makeIntValWithPtrWidth(0,
false));
1920 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
1922 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
1925 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
1926 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
1930 if ( PrtIsNull && !SizeIsZero) {
1936 if (PrtIsNull && SizeIsZero)
1942 SVal RetVal = State->getSVal(CE, LCtx);
1944 if (!FromPtr || !ToPtr)
1947 bool ReleasedAllocated =
false;
1952 false, ReleasedAllocated)){
1962 FreeMemAux(C, CE, State, 0,
false, ReleasedAllocated)) {
1971 Kind = RPIsFreeOnFailure;
1972 else if (!ReleasedAllocated)
1973 Kind = RPDoNotTrackAfterFailure;
1977 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
1978 ReallocPair(FromPtr, Kind));
1981 return stateRealloc;
1996 SVal count = State->getSVal(CE->
getArg(0), LCtx);
1997 SVal elementSize = State->getSVal(CE->
getArg(1), LCtx);
2002 return MallocMemAux(C, CE, TotalSize, zeroVal, State);
2012 const MemRegion *ReferenceRegion =
nullptr;
2016 if (!State->get<RegionState>(Sym))
2021 if (!ReferenceRegion) {
2023 SVal Val = State->getSVal(MR);
2030 ReferenceRegion = MR;
2038 if (NContext == LeakContext ||
2044 return LeakInfo(AllocNode, ReferenceRegion);
2050 if (!ChecksEnabled[CK_MallocChecker] &&
2051 !ChecksEnabled[CK_NewDeleteLeaksChecker])
2054 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2055 assert(RS &&
"cannot leak an untracked symbol");
2058 if (Family == AF_Alloca)
2061 Optional<MallocChecker::CheckKind>
2062 CheckKind = getCheckIfTracked(Family,
true);
2064 if (!CheckKind.hasValue())
2068 if (!BT_Leak[*CheckKind]) {
2069 BT_Leak[*CheckKind].reset(
2070 new BugType(CheckNames[*CheckKind],
"Memory leak",
"Memory Error"));
2076 BT_Leak[*CheckKind]->setSuppressOnSink(
true);
2085 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
2088 const Stmt *AllocationStmt =
nullptr;
2090 AllocationStmt = Exit->getCalleeContext()->getCallSite();
2092 AllocationStmt = SP->getStmt();
2099 llvm::raw_svector_ostream os(buf);
2101 os <<
"Potential leak of memory pointed to by ";
2104 os <<
"Potential memory leak";
2107 auto R = llvm::make_unique<BugReport>(
2108 *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
2110 R->markInteresting(Sym);
2111 R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym,
true));
2115 void MallocChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
2122 RegionStateTy RS = state->get<RegionState>();
2123 RegionStateTy::Factory &F = state->get_context<RegionState>();
2127 if (SymReaper.
isDead(I->first)) {
2128 if (I->second.isAllocated() || I->second.isAllocatedOfSizeZero())
2129 Errors.push_back(I->first);
2131 RS = F.remove(RS, I->first);
2137 ReallocPairsTy RP = state->get<ReallocPairs>();
2139 if (SymReaper.
isDead(I->first) ||
2140 SymReaper.
isDead(I->second.ReallocatedSym)) {
2141 state = state->remove<ReallocPairs>(I->first);
2146 FreeReturnValueTy FR = state->get<FreeReturnValue>();
2148 if (SymReaper.
isDead(I->first) ||
2149 SymReaper.
isDead(I->second)) {
2150 state = state->remove<FreeReturnValue>(I->first);
2156 if (!Errors.empty()) {
2161 I = Errors.begin(), E = Errors.end(); I !=
E; ++
I) {
2162 reportLeak(*I, N, C);
2170 void MallocChecker::checkPreCall(
const CallEvent &Call,
2174 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
2175 if (!Sym || checkDoubleDelete(Sym, C))
2186 if (ChecksEnabled[CK_MallocChecker] &&
2187 (isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
2188 isCMemFunction(FD, Ctx, AF_IfNameIndex,
2189 MemoryOperationKind::MOK_Free)))
2192 if (ChecksEnabled[CK_NewDeleteChecker] &&
2193 isStandardNewDelete(FD, Ctx))
2199 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
2200 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
2205 for (
unsigned I = 0, E = Call.
getNumArgs(); I !=
E; ++
I) {
2211 if (checkUseAfterFree(Sym, C, Call.
getArgExpr(I)))
2231 if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
2234 Sym = BMR->getSymbol();
2238 checkUseAfterFree(Sym, C, E);
2244 void MallocChecker::checkPostStmt(
const BlockExpr *BE,
2254 cast<BlockDataRegion>(state->getSVal(BE,
2267 for ( ; I !=
E; ++
I) {
2268 const VarRegion *VR = I.getCapturedRegion();
2272 Regions.push_back(VR);
2276 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2277 Regions.data() + Regions.size()).getState();
2283 const RefState *RS = C.
getState()->get<RegionState>(Sym);
2284 return (RS && RS->isReleased());
2288 const Stmt *S)
const {
2290 if (isReleased(Sym, C)) {
2291 ReportUseAfterFree(C, S->getSourceRange(), Sym);
2299 const Stmt *S)
const {
2302 if (
const RefState *RS = C.
getState()->get<RegionState>(Sym)) {
2303 if (RS->isAllocatedOfSizeZero())
2304 ReportUseZeroAllocated(C, RS->getStmt()->getSourceRange(), Sym);
2306 else if (C.
getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
2307 ReportUseZeroAllocated(C, S->getSourceRange(), Sym);
2313 if (isReleased(Sym, C)) {
2314 ReportDoubleDelete(C, Sym);
2321 void MallocChecker::checkLocation(
SVal l,
bool isLoad,
const Stmt *S,
2325 checkUseAfterFree(Sym, C, S);
2326 checkUseZeroAllocated(Sym, C, S);
2334 bool Assumption)
const {
2335 RegionStateTy RS = state->get<RegionState>();
2341 state = state->remove<RegionState>(I.getKey());
2346 ReallocPairsTy RP = state->get<ReallocPairs>();
2354 SymbolRef ReallocSym = I.getData().ReallocatedSym;
2355 if (
const RefState *RS = state->get<RegionState>(ReallocSym)) {
2356 if (RS->isReleased()) {
2357 if (I.getData().Kind == RPToBeFreedAfterFailure)
2358 state = state->set<RegionState>(ReallocSym,
2359 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
2360 else if (I.getData().Kind == RPDoNotTrackAfterFailure)
2361 state = state->remove<RegionState>(ReallocSym);
2363 assert(I.getData().Kind == RPIsFreeOnFailure);
2366 state = state->remove<ReallocPairs>(I.getKey());
2372 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
2377 EscapingSymbol =
nullptr;
2383 if (!(isa<SimpleFunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
2387 if (
const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
2403 return *FreeWhenDone;
2409 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
2410 if (FirstSlot.endswith(
"NoCopy"))
2417 if (FirstSlot.startswith(
"addPointer") ||
2418 FirstSlot.startswith(
"insertPointer") ||
2419 FirstSlot.startswith(
"replacePointer") ||
2420 FirstSlot.equals(
"valueWithPointer")) {
2427 if (Msg->getMethodFamily() ==
OMF_init) {
2428 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
2438 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
2442 ASTContext &ASTC = State->getStateManager().getContext();
2446 if (isMemFunction(FD, ASTC))
2457 StringRef FName = II->
getName();
2461 if (FName.endswith(
"NoCopy")) {
2465 for (
unsigned i = 1; i < Call->
getNumArgs(); ++i) {
2467 if (
const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
2468 StringRef DeallocatorName = DE->getFoundDecl()->getName();
2469 if (DeallocatorName ==
"kCFAllocatorNull")
2480 if (FName ==
"funopen")
2487 if (FName ==
"setbuf" || FName ==
"setbuffer" ||
2488 FName ==
"setlinebuf" || FName ==
"setvbuf") {
2491 if (
const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
2492 if (
const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
2493 if (D->getCanonicalDecl()->getName().find(
"std") != StringRef::npos)
2503 if (FName ==
"CGBitmapContextCreate" ||
2504 FName ==
"CGBitmapContextCreateWithData" ||
2505 FName ==
"CVPixelBufferCreateWithBytes" ||
2506 FName ==
"CVPixelBufferCreateWithPlanarBytes" ||
2507 FName ==
"OSAtomicEnqueue") {
2511 if (FName ==
"postEvent" &&
2516 if (FName ==
"postEvent" &&
2538 return (RS->getAllocationFamily() == AF_CXXNewArray ||
2539 RS->getAllocationFamily() == AF_CXXNew);
2546 return checkPointerEscapeAux(State, Escaped, Call, Kind, &
retTrue);
2553 return checkPointerEscapeAux(State, Escaped, Call, Kind,
2561 bool(*CheckRefState)(
const RefState*))
const {
2566 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
2572 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2577 if (EscapingSymbol && EscapingSymbol != sym)
2580 if (
const RefState *RS = State->get<RegionState>(sym)) {
2581 if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) &&
2582 CheckRefState(RS)) {
2583 State = State->remove<RegionState>(sym);
2584 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2593 ReallocPairsTy currMap = currState->get<ReallocPairs>();
2594 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2599 if (!currMap.lookup(sym))
2607 MallocChecker::MallocBugVisitor::VisitNode(
const ExplodedNode *N,
2614 const RefState *RS = state->get<RegionState>(Sym);
2615 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2619 const Stmt *S =
nullptr;
2620 const char *Msg =
nullptr;
2628 S = Exit->getCalleeContext()->getCallSite();
2629 }
else if (Optional<BlockEdge> Edge = ProgLoc.
getAs<
BlockEdge>()) {
2632 S = Edge->getSrc()->getTerminator();
2642 if (Mode == Normal) {
2643 if (isAllocated(RS, RSPrev, S)) {
2644 Msg =
"Memory is allocated";
2646 "Returned allocated memory");
2647 }
else if (isReleased(RS, RSPrev, S)) {
2648 Msg =
"Memory is released";
2650 "Returning; memory was released");
2651 }
else if (isRelinquished(RS, RSPrev, S)) {
2652 Msg =
"Memory ownership is transferred";
2654 }
else if (isReallocFailedCheck(RS, RSPrev, S)) {
2655 Mode = ReallocationFailed;
2656 Msg =
"Reallocation failed";
2657 StackHint =
new StackHintGeneratorForReallocationFailed(Sym,
2658 "Reallocation failed");
2662 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
2663 "We only support one failed realloc at a time.");
2665 FailedReallocSymbol = sym;
2670 }
else if (Mode == ReallocationFailed) {
2671 assert(FailedReallocSymbol &&
"No symbol to look for.");
2674 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
2676 Msg =
"Attempt to reallocate memory";
2678 "Returned reallocated memory");
2679 FailedReallocSymbol =
nullptr;
2694 void MallocChecker::printState(raw_ostream &Out,
ProgramStateRef State,
2695 const char *NL,
const char *Sep)
const {
2697 RegionStateTy RS = State->get<RegionState>();
2699 if (!RS.isEmpty()) {
2700 Out << Sep <<
"MallocChecker :" << NL;
2702 const RefState *RefS = State->get<RegionState>(I.getKey());
2704 Optional<MallocChecker::CheckKind> CheckKind = getCheckIfTracked(Family);
2705 if (!CheckKind.hasValue())
2706 CheckKind = getCheckIfTracked(Family,
true);
2708 I.getKey()->dumpToStream(Out);
2710 I.getData().dump(Out);
2711 if (CheckKind.hasValue())
2712 Out <<
" (" << CheckNames[*CheckKind].getName() <<
")";
2722 "Optimistic",
false, checker);
2723 checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] =
true;
2724 checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
2728 if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker])
2729 checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] =
true;
2732 #define REGISTER_CHECKER(name) \
2733 void ento::register##name(CheckerManager &mgr) { \
2734 registerCStringCheckerBasic(mgr); \
2735 MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
2736 checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
2737 "Optimistic", false, checker); \
2738 checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
2739 checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
bool isInSystemHeader() const
Returns true if the callee is known to be from a system header.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool hasDeadSymbols() const
bool operator==(CanQual< T > x, CanQual< U > y)
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
A helper class which wraps a boolean value set to false by default.
virtual bool argumentsMayEscape() const
Returns true if any of the arguments are known to escape to long- term storage, even if this method w...
const StackFrameContext * getStackFrame() const
Defines the SourceManager interface.
ConstExprIterator const_arg_iterator
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
const RegionTy * getAs() const
Constructs a Stack hint for the given symbol.
Represents a call to a C++ constructor.
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
Represents a C++ constructor within a class.
Value representing integer constant.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
referenced_vars_iterator referenced_vars_begin() const
bool hasCaptures() const
hasCaptures - True if this block (or its nested blocks) captures anything of local storage from its e...
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
const MemRegion * getBaseRegion() const
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
referenced_vars_iterator referenced_vars_end() const
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
const MemSpaceRegion * getMemorySpace() const
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call)
One of these records is kept for each identifier that is lexed.
MemRegionManager & getRegionManager()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent)
Add artificial symbol dependency.
const VarDecl * getDecl() const
static bool isLocType(QualType T)
void registerCStringCheckerBasic(CheckerManager &Mgr)
Register the checker which evaluates CString API calls.
BlockDataRegion - A region that represents a block instance.
Represents any expression that calls an Objective-C method.
const TargetInfo & getTargetInfo() const
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
SymbolRef getSymbol() const
bool isUnknownOrUndef() const
bool isParentOf(const LocationContext *LC) const
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
bool isVariadic() const
Whether this function is variadic.
StringRef getDescription() const
detail::InMemoryDirectory::const_iterator I
Represent a region's offset within the top level base region.
static bool didPreviousFreeFail(ProgramStateRef State, SymbolRef Sym, SymbolRef &RetStatusSymbol)
Checks if the previous call to free on the given symbol failed - if free failed, returns true...
arg_iterator placement_arg_end()
const MemRegion * getSuperRegion() const
const LocationContext * getLocationContext() const
FunctionDecl * getOperatorDelete() const
Represents a non-static C++ member function call, no matter how it is written.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const MemRegion * StripCasts(bool StripBaseCasts=true) const
Represents a point when we finish the call exit sequence (for inlined call).
ID
Defines the set of possible language-specific address spaces.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SymbolicRegion - A special, "non-concrete" region.
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Expr - This represents one expression.
const ProgramStateRef & getState() const
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
unsigned getNumArgs() const
CheckName getCurrentCheckName() const
Represents an implicit call to a C++ destructor.
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override
getExtent - Returns the size of the region in bytes.
static bool retTrue(const RefState *RS)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
ParentMap & getParentMap() const
bool hasSymbolicOffset() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
The pointer has been passed to a function call directly.
Represents a call to any sort of function that might have a FunctionDecl.
const ParmVarDecl * getParamDecl(unsigned i) const
SymbolManager & getSymbolManager()
QualType getAllocatedType() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
An expression that sends a message to the given Objective-C object or class.
const IdentifierInfo * getBaseTypeIdentifier() const
Retrieves a pointer to the name of the base type.
void markInteresting(SymbolRef sym)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
The result type of a method or function.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
bool isConsumedExpr(Expr *E) const
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
unsigned getNumParams() const
getNumParams - Return the number of parameters this function must have based on its FunctionType...
const TemplateArgument * iterator
const StackFrameContext * getCurrentStackFrame() const
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
ASTContext & getContext()
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Selector getSelector() const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
const Decl * getDecl() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
A class responsible for cleaning up unused symbols.
static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState)
DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, const LocationContext *LCtx, unsigned Count)
Conjure a symbol representing heap allocated memory region.
const BlockDecl * getBlockDecl() const
static bool treatUnusedNewEscaped(const CXXNewExpr *NE)
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
ASTContext & getASTContext()
Represents a delete expression for memory deallocation and destructor calls, e.g. ...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
static QualType getDeepPointeeType(QualType T)
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
unsigned getNumPlacementArgs() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
const Expr * getRetValue() const
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Represents an abstract call to a function or method along a particular path.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalyzerOptions & getAnalyzerOptions()
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
FunctionDecl * getOperatorNew() const
#define REGISTER_CHECKER(name)
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword...
int64_t getOffset() const
static Optional< bool > getFreeWhenDoneArg(const ObjCMethodCall &Call)
CXXConstructorDecl * getConstructor() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
uint64_t getCharWidth() const
Return the size of the character type, in bits.
arg_iterator placement_arg_begin()
std::string getQualifiedNameAsString() const
const CXXConstructExpr * getConstructExpr() const
Returns the CXXConstructExpr from this new-expression, or null.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
const Expr * getArgExpr(unsigned Index) const override
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
pred_iterator pred_begin()
SourceManager & getSourceManager()
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
SValBuilder & getSValBuilder()
Defines the clang::TargetInfo interface.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ElementRegin is used to represent both array elements and casts.
A reference to a declared variable, function, enum, etc.
static const MemRegion * getLocationRegionIfPostStore(const ExplodedNode *N)
If the given node corresponds to a PostStore program point, retrieve the location region as it was ut...
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
This class provides an interface through which checkers can create individual bug reports...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
virtual const ObjCMessageExpr * getOriginExpr() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SourceManager & getSourceManager()
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any...