49 #include "llvm/ADT/ArrayRef.h" 50 #include "llvm/ADT/None.h" 51 #include "llvm/ADT/Optional.h" 52 #include "llvm/ADT/STLExtras.h" 53 #include "llvm/ADT/SmallPtrSet.h" 54 #include "llvm/ADT/SmallString.h" 55 #include "llvm/ADT/SmallVector.h" 56 #include "llvm/ADT/StringExtras.h" 57 #include "llvm/ADT/StringRef.h" 58 #include "llvm/Support/Casting.h" 59 #include "llvm/Support/ErrorHandling.h" 60 #include "llvm/Support/raw_ostream.h" 67 using namespace clang;
97 const Expr *bugreporter::getDerefExpr(
const Stmt *S) {
98 const auto *E = dyn_cast<
Expr>(S);
103 if (
const auto *CE = dyn_cast<CastExpr>(E)) {
104 if (CE->getCastKind() == CK_LValueToRValue) {
108 E = CE->getSubExpr();
109 }
else if (
const auto *B = dyn_cast<BinaryOperator>(E)) {
118 }
else if (
const auto *U = dyn_cast<UnaryOperator>(E)) {
119 if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf ||
120 (U->isIncrementDecrementOp() && U->getType()->isPointerType())) {
131 else if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
133 }
else if (
const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
134 E = IvarRef->getBase();
135 }
else if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) {
137 }
else if (
const auto *PE = dyn_cast<ParenExpr>(E)) {
138 E = PE->getSubExpr();
139 }
else if (
const auto *FE = dyn_cast<FullExpr>(E)) {
140 E = FE->getSubExpr();
150 if (
const auto *CE = dyn_cast<ImplicitCastExpr>(E))
151 if (CE->getCastKind() == CK_LValueToRValue)
152 E = CE->getSubExpr();
161 std::shared_ptr<PathDiagnosticPiece>
162 BugReporterVisitor::getEndPath(BugReporterContext &,
163 const ExplodedNode *, BugReport &) {
168 BugReporterVisitor::finalizeVisitor(BugReporterContext &,
169 const ExplodedNode *, BugReport &) {}
171 std::shared_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
172 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
173 PathDiagnosticLocation L =
176 const auto &Ranges = BR.getRanges();
180 auto P = std::make_shared<PathDiagnosticEventPiece>(
181 L, BR.getDescription(), Ranges.begin() == Ranges.end());
190 BugReporterContext &BRC) {
193 BRC.getSourceManager(),
194 BRC.getASTContext().getLangOpts());
215 const SubRegion *RegionOfInterest,
216 const ExplodedNode *N,
219 ProgramStateManager &Mgr = N->getState()->getStateManager();
227 if (
auto PS = N->getLocationAs<
PostStmt>())
229 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
230 N->getSVal(BO->getLHS()).getAsRegion()))
234 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
235 if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() &&
236 (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
250 const SubRegion *RegionOfInterest;
251 MemRegionManager &MmrMgr;
258 static const unsigned DEREFERENCE_LIMIT = 2;
268 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
269 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
273 NoStoreFuncVisitor(
const SubRegion *R)
274 : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
275 SM(MmrMgr.getContext().getSourceManager()),
276 PP(MmrMgr.getContext().getPrintingPolicy()) {}
278 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
281 ID.AddPointer(RegionOfInterest);
284 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
285 BugReporterContext &BR,
286 BugReport &)
override {
294 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
297 CallEventRef<> Call =
298 BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
305 if (
const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
306 if (
const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
307 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
308 if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
309 potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
311 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, SelfRegion,
317 if (
const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
318 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
319 if (RegionOfInterest->isSubRegionOf(ThisR)
320 && !CCall->getDecl()->isImplicit())
321 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, ThisR,
331 for (
unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
333 SVal S = Call->getArgSVal(I);
337 int IndirectionLevel = 1;
339 while (
const MemRegion *R = S.getAsRegion()) {
341 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, R,
342 ParamName, ParamIsReferenceType,
349 if (
auto P = findRegionOfInterestInRecord(RD, State, R))
350 return notModifiedDiagnostics(
351 Ctx, *CallExitLoc, Call, *
P, RegionOfInterest, ParamName,
352 ParamIsReferenceType, IndirectionLevel);
354 S = State->getSVal(R, PT);
373 const RegionVector &Vec = {},
376 if (depth == DEREFERENCE_LIMIT)
379 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
380 if (!RDX->hasDefinition())
385 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
386 for (
const auto II : RDX->bases())
387 if (
const RecordDecl *RRD = II.getType()->getAsRecordDecl())
388 if (
auto Out = findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
393 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
394 const SVal V = State->getSVal(FR);
395 const MemRegion *VR = V.getAsRegion();
397 RegionVector VecF = Vec;
400 if (RegionOfInterest == VR)
405 findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
413 findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
423 bool potentiallyWritesIntoIvar(
const Decl *
Parent,
426 const char * IvarBind =
"Ivar";
427 if (!Parent || !Parent->
hasBody())
430 hasOperatorName(
"="),
431 hasLHS(ignoringParenImpCasts(
437 if (IvarRef->isFreeIvar())
440 const Expr *
Base = IvarRef->getBase();
441 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
442 Base = ICE->getSubExpr();
444 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Base))
445 if (
const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
457 bool isRegionOfInterestModifiedInFrame(
const ExplodedNode *N) {
460 if (!FramesModifyingCalculated.count(SCtx))
461 findModifyingFrames(N);
462 return FramesModifyingRegion.count(SCtx);
468 void findModifyingFrames(
const ExplodedNode *N) {
471 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
479 LastReturnState =
State;
480 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
483 FramesModifyingCalculated.insert(
484 N->getLocationContext()->getStackFrame());
489 auto p = FramesModifyingRegion.insert(SCtx);
497 if (
auto CE = N->getLocationAs<
CallEnter>())
498 if (CE->getCalleeContext() == OriginalSCtx)
501 N = N->getFirstPred();
509 RuntimeDefinition RD = Call->getRuntimeDefinition();
510 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
511 return FD->parameters();
512 if (
const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
513 return MD->parameters();
515 return Call->parameters();
525 std::shared_ptr<PathDiagnosticPiece>
527 CallEventRef<> Call,
const RegionVector &FieldChain,
528 const MemRegion *MatchedRegion, StringRef FirstElement,
529 bool FirstIsReferenceType,
unsigned IndirectionLevel) {
531 PathDiagnosticLocation L;
535 L = PathDiagnosticLocation(
536 Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(),
541 llvm::raw_svector_ostream os(sbuf);
542 os <<
"Returning without writing to '";
545 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType,
546 MatchedRegion, FieldChain, IndirectionLevel, os))
550 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
555 bool prettyPrintRegionName(StringRef FirstElement,
bool FirstIsReferenceType,
556 const MemRegion *MatchedRegion,
557 const RegionVector &FieldChain,
558 int IndirectionLevel,
559 llvm::raw_svector_ostream &os) {
561 if (FirstIsReferenceType)
564 RegionVector RegionSequence;
567 assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
568 const MemRegion *R = RegionOfInterest;
569 while (R != MatchedRegion) {
570 RegionSequence.push_back(R);
571 R = cast<SubRegion>(R)->getSuperRegion();
573 std::reverse(RegionSequence.begin(), RegionSequence.end());
574 RegionSequence.append(FieldChain.begin(), FieldChain.end());
577 for (
const MemRegion *R : RegionSequence) {
581 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
585 Sep = prettyPrintFirstElement(FirstElement,
587 IndirectionLevel, os);
592 if (!isa<DeclRegion>(R))
595 const auto *DR = cast<DeclRegion>(R);
596 Sep = DR->getValueType()->isAnyPointerType() ?
"->" :
".";
597 DR->getDecl()->getDeclName().print(os, PP);
601 prettyPrintFirstElement(FirstElement,
602 false, IndirectionLevel,
608 StringRef prettyPrintFirstElement(StringRef FirstElement,
609 bool MoreItemsExpected,
610 int IndirectionLevel,
611 llvm::raw_svector_ostream &os) {
614 if (IndirectionLevel > 0 && MoreItemsExpected) {
619 if (IndirectionLevel > 0 && MoreItemsExpected)
622 for (
int i=0; i<IndirectionLevel; i++)
626 if (IndirectionLevel > 0 && MoreItemsExpected)
636 const SubRegion *RegionOfInterest;
637 const SVal ValueAtDereference;
641 bool WasModified =
false;
644 MacroNullReturnSuppressionVisitor(
const SubRegion *R,
645 const SVal V) : RegionOfInterest(R),
646 ValueAtDereference(V) {}
648 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
649 BugReporterContext &BRC,
650 BugReport &BR)
override {
654 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
659 if (
auto Loc = matchAssignment(N)) {
664 BR.markInvalid(getTag(), MacroName.c_str());
674 static void addMacroVisitorIfNecessary(
675 const ExplodedNode *N,
const MemRegion *R,
676 bool EnableNullFPSuppression, BugReport &BR,
678 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
679 if (EnableNullFPSuppression &&
680 Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
681 BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
682 R->getAs<SubRegion>(), V));
685 void* getTag()
const {
687 return static_cast<void *
>(&Tag);
690 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
691 ID.AddPointer(getTag());
700 auto *LCtx = N->getLocationContext();
704 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
705 if (
const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
706 if (
const Expr *RHS = VD->getInit())
707 if (RegionOfInterest->isSubRegionOf(
708 State->getLValue(VD, LCtx).getAsRegion()))
709 return RHS->getBeginLoc();
710 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(S)) {
711 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
712 const Expr *RHS = BO->getRHS();
713 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
736 bool EnableNullFPSuppression;
737 bool ShouldInvalidate =
true;
744 : StackFrame(Frame), EnableNullFPSuppression(Suppressed),
747 static void *getTag() {
749 return static_cast<void *
>(&Tag);
752 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
753 ID.AddPointer(ReturnVisitor::getTag());
754 ID.AddPointer(StackFrame);
755 ID.AddBoolean(EnableNullFPSuppression);
765 static void addVisitorIfNecessary(
const ExplodedNode *
Node,
const Stmt *S,
767 bool InEnableNullFPSuppression) {
774 if (CEE->getCalleeContext()->getCallSite() == S)
776 if (
auto SP = Node->getLocationAs<
StmtPoint>())
777 if (SP->getStmt() == S)
780 Node = Node->getFirstPred();
784 while (Node && Node->getLocation().getAs<
PostStmt>())
785 Node = Node->getFirstPred();
800 SVal RetVal = Node->getSVal(S);
803 if (cast<Expr>(S)->isGLValue())
805 RetVal = State->getSVal(*LValue);
810 bool EnableNullFPSuppression =
false;
811 if (InEnableNullFPSuppression &&
812 Options.ShouldSuppressNullReturnPaths)
814 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
816 BR.markInteresting(CalleeContext);
817 BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
818 EnableNullFPSuppression,
822 std::shared_ptr<PathDiagnosticPiece>
823 visitNodeInitial(
const ExplodedNode *N,
824 BugReporterContext &BRC, BugReport &BR) {
826 if (N->getLocationContext() != StackFrame)
833 const auto *Ret = dyn_cast<
ReturnStmt>(SP->getStmt());
840 SVal V = State->getSVal(Ret, StackFrame);
841 if (V.isUnknownOrUndef())
847 const Expr *RetE = Ret->getRetValue();
848 assert(RetE &&
"Tracking a return value for a void function");
853 if ((LValue = V.getAs<Loc>())) {
854 SVal RValue = State->getRawSVal(*LValue, RetE->
getType());
855 if (RValue.getAs<DefinedSVal>())
861 if (V.getAs<nonloc::LazyCompoundVal>() ||
862 V.getAs<nonloc::CompoundVal>())
868 bugreporter::trackExpressionValue(N, RetE, BR, EnableNullFPSuppression);
872 llvm::raw_svector_ostream Out(Msg);
874 if (State->isNull(V).isConstrainedTrue()) {
875 if (V.getAs<Loc>()) {
880 if (EnableNullFPSuppression &&
881 Options.ShouldAvoidSuppressingNullArgumentPaths)
882 Mode = MaybeUnsuppress;
885 Out <<
"Returning nil";
887 Out <<
"Returning null pointer";
890 Out <<
"Returning zero";
894 if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
895 Out <<
"Returning the value " << CI->getValue();
896 }
else if (V.getAs<Loc>()) {
897 Out <<
"Returning pointer";
899 Out <<
"Returning value";
904 if (
const MemRegion *MR = LValue->getAsRegion()) {
905 if (MR->canPrintPretty()) {
906 Out <<
" (reference to ";
907 MR->printPretty(Out);
913 if (
const auto *DR = dyn_cast<DeclRefExpr>(RetE))
914 if (
const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
915 Out <<
" (loaded from '" << *DD <<
"')";
918 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
919 if (!L.isValid() || !L.asLocation().isValid())
922 return std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
925 std::shared_ptr<PathDiagnosticPiece>
926 visitNodeMaybeUnsuppress(
const ExplodedNode *N,
927 BugReporterContext &BRC, BugReport &BR) {
929 assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
937 if (CE->getCalleeContext() != StackFrame)
945 ProgramStateManager &StateMgr = BRC.getStateManager();
949 CallEventRef<> Call = CallMgr.
getCaller(StackFrame, State);
950 for (
unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
955 const Expr *ArgE = Call->getArgExpr(I);
960 if (!State->isNull(*ArgV).isConstrainedTrue())
963 if (bugreporter::trackExpressionValue(N, ArgE, BR, EnableNullFPSuppression))
964 ShouldInvalidate =
false;
974 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
975 BugReporterContext &BRC,
976 BugReport &BR)
override {
979 return visitNodeInitial(N, BRC, BR);
980 case MaybeUnsuppress:
981 return visitNodeMaybeUnsuppress(N, BRC, BR);
986 llvm_unreachable(
"Invalid visit mode!");
989 void finalizeVisitor(BugReporterContext &,
const ExplodedNode *,
990 BugReport &BR)
override {
991 if (EnableNullFPSuppression && ShouldInvalidate)
992 BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
998 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1000 ID.AddPointer(&tag);
1003 ID.AddBoolean(EnableNullFPSuppression);
1020 const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1021 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1026 assert(VR->getDecl()->isStaticLocal() &&
"non-static stackless VarRegion");
1030 assert(VR->getDecl()->hasLocalStorage());
1037 const MemRegion *R, SVal V,
const DeclStmt *DS) {
1038 if (R->canPrintPretty()) {
1043 if (V.getAs<loc::ConcreteInt>()) {
1045 if (R->isBoundable()) {
1046 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1047 if (TR->getValueType()->isObjCObjectPointerType()) {
1048 os << action <<
"nil";
1054 os << action <<
"a null pointer value";
1056 }
else if (
auto CVal = V.getAs<nonloc::ConcreteInt>()) {
1057 os << action << CVal->getValue();
1060 if (isa<VarRegion>(R)) {
1062 if (VD->getInit()) {
1063 os << (R->canPrintPretty() ?
"initialized" :
"Initializing")
1064 <<
" to a garbage value";
1066 os << (R->canPrintPretty() ?
"declared" :
"Declaring")
1067 <<
" without an initial value";
1071 os << (R->canPrintPretty() ?
"initialized" :
"Initialized")
1079 const VarRegion *VR,
1081 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1085 if (V.getAs<loc::ConcreteInt>()) {
1086 if (Param->getType()->isObjCObjectPointerType())
1087 os <<
"nil object reference";
1089 os <<
"null pointer value";
1090 }
else if (V.isUndef()) {
1091 os <<
"uninitialized value";
1092 }
else if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1093 os <<
"the value " << CI->getValue();
1099 unsigned Idx = Param->getFunctionScopeIndex() + 1;
1100 os <<
" via " << Idx << llvm::getOrdinalSuffix(Idx) <<
" parameter";
1101 if (VR->canPrintPretty()) {
1103 VR->printPretty(os);
1111 if (V.getAs<loc::ConcreteInt>()) {
1113 if (R->isBoundable()) {
1114 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1115 if (TR->getValueType()->isObjCObjectPointerType()) {
1116 os <<
"nil object reference stored";
1122 if (R->canPrintPretty())
1123 os <<
"Null pointer value stored";
1125 os <<
"Storing null pointer value";
1128 }
else if (V.isUndef()) {
1129 if (R->canPrintPretty())
1130 os <<
"Uninitialized value stored";
1132 os <<
"Storing uninitialized value";
1134 }
else if (
auto CV = V.getAs<nonloc::ConcreteInt>()) {
1135 if (R->canPrintPretty())
1136 os <<
"The value " << CV->getValue() <<
" is assigned";
1138 os <<
"Assigning " << CV->getValue();
1141 if (R->canPrintPretty())
1142 os <<
"Value assigned";
1144 os <<
"Assigning value";
1147 if (R->canPrintPretty()) {
1153 std::shared_ptr<PathDiagnosticPiece>
1154 FindLastStoreBRVisitor::VisitNode(
const ExplodedNode *Succ,
1155 BugReporterContext &BRC, BugReport &BR) {
1159 const ExplodedNode *StoreSite =
nullptr;
1160 const ExplodedNode *Pred = Succ->getFirstPred();
1161 const Expr *InitE =
nullptr;
1162 bool IsParam =
false;
1165 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1168 InitE = VR->getDecl()->getInit();
1175 const MemRegion *FieldReg = (
const MemRegion *)PIP->getLocationValue();
1176 if (FieldReg && FieldReg == R) {
1178 InitE = PIP->getInitializer()->getInit();
1188 if (Succ->getState()->getSVal(R) != V)
1191 if (Pred->getState()->getSVal(R) == V) {
1193 if (!PS || PS->getLocationValue() != R)
1203 if (BO->isAssignmentOp())
1204 InitE = BO->getRHS();
1211 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1212 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1214 ProgramStateManager &StateMgr = BRC.getStateManager();
1217 CallEventRef<> Call = CallMgr.
getCaller(CE->getCalleeContext(),
1219 InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1226 if (
const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1227 InitE = TmpR->getExpr();
1238 V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1241 bugreporter::trackExpressionValue(StoreSite, InitE, BR,
1242 EnableNullFPSuppression);
1245 BR, EnableNullFPSuppression);
1250 llvm::raw_svector_ostream os(sbuf);
1253 const Stmt *S = PS->getStmt();
1254 const char *action =
nullptr;
1255 const auto *DS = dyn_cast<
DeclStmt>(S);
1256 const auto *VR = dyn_cast<VarRegion>(R);
1259 action = R->canPrintPretty() ?
"initialized to " :
1261 }
else if (isa<BlockExpr>(S)) {
1262 action = R->canPrintPretty() ?
"captured by block as " :
1263 "Captured by block as ";
1267 SVal V = StoreSite->getSVal(S);
1268 if (
const auto *BDR =
1269 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1270 if (
const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1271 if (
auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
1272 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1273 *KV, OriginalR, EnableNullFPSuppression));
1281 }
else if (StoreSite->getLocation().getAs<
CallEnter>()) {
1282 if (
const auto *VR = dyn_cast<VarRegion>(R))
1286 if (os.str().empty())
1291 PathDiagnosticLocation L;
1293 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
1296 if (!L.isValid() || !L.asLocation().isValid())
1299 if (!L.isValid() || !L.asLocation().isValid())
1302 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1305 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1307 ID.AddPointer(&tag);
1308 ID.AddBoolean(Assumption);
1314 const char *TrackConstraintBRVisitor::getTag() {
1315 return "TrackConstraintBRVisitor";
1318 bool TrackConstraintBRVisitor::isUnderconstrained(
const ExplodedNode *N)
const {
1320 return N->getState()->isNull(Constraint).isUnderconstrained();
1321 return (
bool)N->getState()->assume(Constraint, !Assumption);
1324 std::shared_ptr<PathDiagnosticPiece>
1325 TrackConstraintBRVisitor::VisitNode(
const ExplodedNode *N,
1326 BugReporterContext &BRC, BugReport &) {
1327 const ExplodedNode *PrevN = N->getFirstPred();
1333 if (!IsTrackingTurnedOn)
1334 if (!isUnderconstrained(N))
1335 IsTrackingTurnedOn =
true;
1336 if (!IsTrackingTurnedOn)
1341 if (isUnderconstrained(PrevN)) {
1347 assert(!isUnderconstrained(N));
1352 llvm::raw_svector_ostream os(sbuf);
1354 if (Constraint.getAs<Loc>()) {
1355 os <<
"Assuming pointer value is ";
1356 os << (Assumption ?
"non-null" :
"null");
1359 if (os.str().empty())
1364 PathDiagnosticLocation L =
1369 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1370 X->setTag(getTag());
1371 return std::move(
X);
1377 SuppressInlineDefensiveChecksVisitor::
1378 SuppressInlineDefensiveChecksVisitor(DefinedSVal
Value,
const ExplodedNode *N)
1381 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1382 if (!Options.ShouldSuppressInlinedDefensiveChecks)
1385 assert(N->getState()->isNull(V).isConstrainedTrue() &&
1386 "The visitor only tracks the cases where V is constrained to 0");
1389 void SuppressInlineDefensiveChecksVisitor::Profile(
1390 llvm::FoldingSetNodeID &
ID)
const {
1396 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1397 return "IDCVisitor";
1400 std::shared_ptr<PathDiagnosticPiece>
1401 SuppressInlineDefensiveChecksVisitor::VisitNode(
const ExplodedNode *Succ,
1402 BugReporterContext &BRC,
1404 const ExplodedNode *Pred = Succ->getFirstPred();
1409 if (!IsTrackingTurnedOn)
1410 if (Succ->getState()->isNull(V).isConstrainedTrue())
1411 IsTrackingTurnedOn =
true;
1412 if (!IsTrackingTurnedOn)
1417 if (!Pred->getState()->isNull(V).isConstrainedTrue()) {
1420 assert(Succ->getState()->isNull(V).isConstrainedTrue());
1424 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1425 if (CurLC != ReportLC && !CurLC->
isParentOf(ReportLC)) {
1426 BR.markInvalid(
"Suppress IDC", CurLC);
1434 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
1440 const Stmt *CurTerminatorStmt =
nullptr;
1442 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1444 const Stmt *CurStmt = SP->getStmt();
1448 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1454 if (!CurTerminatorStmt)
1464 BR.markInvalid(
"Suppress Macro IDC", CurLC);
1473 const ExplodedNode *N) {
1474 if (
const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1475 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1476 if (!VD->getType()->isReferenceType())
1478 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1479 MemRegionManager &MRMgr = StateMgr.getRegionManager();
1480 return MRMgr.getVarRegion(VD, N->getLocationContext());
1495 static const Expr *peelOffOuterExpr(
const Expr *Ex,
1496 const ExplodedNode *N) {
1498 if (
const auto *FE = dyn_cast<FullExpr>(Ex))
1499 return peelOffOuterExpr(FE->getSubExpr(), N);
1500 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1501 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1502 if (
const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1504 if (PropRef && PropRef->isMessagingGetter()) {
1505 const Expr *GetterMessageSend =
1506 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1508 return peelOffOuterExpr(GetterMessageSend, N);
1513 if (
const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1516 const ExplodedNode *NI = N;
1520 const CFGBlock *srcBlk = BE->getSrc();
1523 bool TookTrueBranch = (*(srcBlk->
succ_begin()) == BE->getDst());
1525 return peelOffOuterExpr(CO->getTrueExpr(), N);
1527 return peelOffOuterExpr(CO->getFalseExpr(), N);
1531 NI = NI->getFirstPred();
1535 if (
auto *BO = dyn_cast<BinaryOperator>(Ex))
1537 return peelOffOuterExpr(SubEx, N);
1539 if (
auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1540 if (UO->getOpcode() == UO_LNot)
1541 return peelOffOuterExpr(UO->getSubExpr(), N);
1551 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1552 if (
const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1553 return peelOffOuterExpr(DerefEx, N);
1561 static const ExplodedNode* findNodeForExpression(
const ExplodedNode *N,
1562 const Expr *Inner) {
1566 N = N->getFirstPred();
1571 bool bugreporter::trackExpressionValue(
const ExplodedNode *InputNode,
1572 const Expr *E, BugReport &report,
1573 bool EnableNullFPSuppression) {
1574 if (!E || !InputNode)
1577 const Expr *Inner = peelOffOuterExpr(E, InputNode);
1578 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1587 if (
const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1588 trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression);
1593 SVal LVal = LVNode->getSVal(Inner);
1596 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
1601 if (RR && !LVIsNull)
1602 if (
auto KV = LVal.getAs<KnownSVal>())
1603 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1604 *KV, RR, EnableNullFPSuppression));
1610 const MemRegion *R = (RR && LVIsNull) ? RR :
1611 LVNode->getSVal(Inner).getAsRegion();
1616 SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
1618 llvm::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R)));
1620 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
1621 LVNode, R, EnableNullFPSuppression, report, V);
1623 report.markInteresting(V);
1624 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1627 if (V.getAsLocSymbol(
true))
1628 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1629 V.castAs<DefinedSVal>(),
false));
1632 if (
auto DV = V.getAs<DefinedSVal>())
1633 if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1634 EnableNullFPSuppression)
1636 llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1639 if (
auto KV = V.getAs<KnownSVal>())
1640 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1641 *KV, R, EnableNullFPSuppression));
1648 SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
1650 ReturnVisitor::addVisitorIfNecessary(
1651 LVNode, Inner, report, EnableNullFPSuppression);
1654 if (
auto L = V.getAs<loc::MemRegionVal>()) {
1655 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1661 bool CanDereference =
true;
1662 if (
const auto *SR = dyn_cast<SymbolicRegion>(L->getRegion()))
1663 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
1664 CanDereference =
false;
1671 RVal = LVState->getRawSVal(L.getValue(), Inner->
getType());
1672 }
else if (CanDereference) {
1673 RVal = LVState->getSVal(L->getRegion());
1677 if (
auto KV = RVal.getAs<KnownSVal>())
1678 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1679 *KV, L->getRegion(), EnableNullFPSuppression));
1681 const MemRegion *RegionRVal = RVal.getAsRegion();
1682 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1683 report.markInteresting(RegionRVal);
1684 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1685 loc::MemRegionVal(RegionRVal),
false));
1691 const Expr *NilReceiverBRVisitor::getNilReceiver(
const Stmt *S,
1692 const ExplodedNode *N) {
1696 if (
const Expr *Receiver = ME->getInstanceReceiver()) {
1698 SVal V = N->getSVal(Receiver);
1699 if (state->isNull(V).isConstrainedTrue())
1705 std::shared_ptr<PathDiagnosticPiece>
1706 NilReceiverBRVisitor::VisitNode(
const ExplodedNode *N,
1707 BugReporterContext &BRC, BugReport &BR) {
1712 const Stmt *S = P->getStmt();
1713 const Expr *Receiver = getNilReceiver(S, N);
1718 llvm::raw_svector_ostream
OS(Buf);
1720 if (
const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
1722 ME->getSelector().print(OS);
1723 OS <<
"' not called";
1726 OS <<
"No method is called";
1728 OS <<
" because the receiver is nil";
1733 bugreporter::trackExpressionValue(N, Receiver, BR,
1736 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
1737 N->getLocationContext());
1738 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
1742 void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
1744 bool EnableNullFPSuppression) {
1745 const ExplodedNode *N = BR.getErrorNode();
1746 std::deque<const Stmt *> WorkList;
1747 WorkList.push_back(S);
1749 while (!WorkList.empty()) {
1750 const Stmt *Head = WorkList.front();
1751 WorkList.pop_front();
1753 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1755 if (
const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
1756 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1757 const VarRegion *R =
1758 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
1761 SVal V = N->getSVal(S);
1763 if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1765 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1766 V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
1772 WorkList.push_back(SubStmt);
1782 const char *ConditionBRVisitor::getTag() {
1783 return "ConditionBRVisitor";
1786 std::shared_ptr<PathDiagnosticPiece>
1787 ConditionBRVisitor::VisitNode(
const ExplodedNode *N,
1788 BugReporterContext &BRC, BugReport &BR) {
1789 auto piece = VisitNodeImpl(N, BRC, BR);
1791 piece->setTag(getTag());
1792 if (
auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
1793 ev->setPrunable(
true,
false);
1798 std::shared_ptr<PathDiagnosticPiece>
1799 ConditionBRVisitor::VisitNodeImpl(
const ExplodedNode *N,
1800 BugReporterContext &BRC, BugReport &BR) {
1808 if (CurrentState->getGDM().getRoot() ==
1809 PrevState->getGDM().getRoot())
1815 const CFGBlock *srcBlk = BE->getSrc();
1817 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
1822 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
1826 if (tag == tags.first)
1827 return VisitTrueTest(cast<Expr>(PS->getStmt()),
true,
1829 if (tag == tags.second)
1830 return VisitTrueTest(cast<Expr>(PS->getStmt()),
false,
1839 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTerminator(
1840 const Stmt *Term,
const ExplodedNode *N,
const CFGBlock *srcBlk,
1841 const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
1842 const Expr *Cond =
nullptr;
1862 case Stmt::IfStmtClass:
1863 Cond = cast<IfStmt>(Term)->getCond();
1865 case Stmt::ConditionalOperatorClass:
1866 Cond = cast<ConditionalOperator>(Term)->getCond();
1868 case Stmt::BinaryOperatorClass:
1872 const auto *BO = cast<BinaryOperator>(Term);
1873 assert(BO->isLogicalOp() &&
1874 "CFG terminator is not a short-circuit operator!");
1875 Cond = BO->getLHS();
1882 while (
const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
1883 if (!InnerBO->isLogicalOp())
1890 const bool tookTrue = *(srcBlk->
succ_begin()) == dstBlk;
1891 return VisitTrueTest(Cond, tookTrue, BRC, R, N);
1894 std::shared_ptr<PathDiagnosticPiece>
1895 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond,
bool tookTrue,
1896 BugReporterContext &BRC, BugReport &R,
1897 const ExplodedNode *N) {
1900 const Expr *CondTmp = Cond;
1901 bool tookTrueTmp = tookTrue;
1908 case Stmt::BinaryOperatorClass:
1909 if (
auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
1910 tookTrueTmp, BRC, R, N))
1913 case Stmt::DeclRefExprClass:
1914 if (
auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
1915 tookTrueTmp, BRC, R, N))
1918 case Stmt::UnaryOperatorClass: {
1919 const auto *UO = cast<UnaryOperator>(CondTmp);
1920 if (UO->getOpcode() == UO_LNot) {
1921 tookTrueTmp = !tookTrueTmp;
1922 CondTmp = UO->getSubExpr();
1934 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1935 if (!Loc.isValid() || !Loc.asLocation().isValid())
1938 return std::make_shared<PathDiagnosticEventPiece>(
1939 Loc, tookTrue ? GenericTrueMessage : GenericFalseMessage);
1942 bool ConditionBRVisitor::patternMatch(
const Expr *Ex,
1943 const Expr *ParentEx,
1945 BugReporterContext &BRC,
1947 const ExplodedNode *N,
1949 const Expr *OriginalExpr = Ex;
1957 (isa<GNUNullExpr>(Ex) ||
1958 isa<ObjCBoolLiteralExpr>(Ex) ||
1959 isa<CXXBoolLiteralExpr>(Ex) ||
1960 isa<IntegerLiteral>(Ex) ||
1961 isa<FloatingLiteral>(Ex))) {
1963 BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1965 BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1966 bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
1968 bool partOfParentMacro =
false;
1972 BRC.getASTContext().getLangOpts());
1973 partOfParentMacro = PName.equals(StartName);
1976 if (beginAndEndAreTheSameMacro && !partOfParentMacro ) {
1981 LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart);
1984 Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1992 if (
const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
1993 const bool quotes = isa<VarDecl>(DR->getDecl());
1997 const ProgramState *
state = N->getState().get();
1998 if (
const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
1999 LCtx).getAsRegion()) {
2000 if (report.isInteresting(R))
2003 const ProgramState *state = N->getState().get();
2004 SVal V = state->getSVal(R);
2005 if (report.isInteresting(V))
2010 Out << DR->getDecl()->getDeclName().getAsString();
2016 if (
const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2019 if (IL->getValue() == 0) {
2025 if (IL->getValue() == 0) {
2031 Out << IL->getValue();
2038 std::shared_ptr<PathDiagnosticPiece>
2040 const bool tookTrue, BugReporterContext &BRC,
2041 BugReport &R,
const ExplodedNode *N) {
2042 bool shouldInvert =
false;
2047 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2048 const bool isVarLHS = patternMatch(BExpr->
getLHS(), BExpr, OutLHS,
2049 BRC, R, N, shouldPrune);
2050 const bool isVarRHS = patternMatch(BExpr->
getRHS(), BExpr, OutRHS,
2051 BRC, R, N, shouldPrune);
2053 shouldInvert = !isVarLHS && isVarRHS;
2061 return VisitConditionVariable(LhsString, BExpr->
getLHS(), tookTrue,
2067 if (LhsString.empty() || RhsString.empty() ||
2073 llvm::raw_svector_ostream Out(buf);
2074 Out <<
"Assuming " << (shouldInvert ? RhsString : LhsString) <<
" is ";
2080 case BO_LT: Op = BO_GT;
break;
2081 case BO_GT: Op = BO_LT;
break;
2082 case BO_LE: Op = BO_GE;
break;
2083 case BO_GE: Op = BO_LE;
break;
2088 case BO_EQ: Op = BO_NE;
break;
2089 case BO_NE: Op = BO_EQ;
break;
2090 case BO_LT: Op = BO_GE;
break;
2091 case BO_GT: Op = BO_LE;
break;
2092 case BO_LE: Op = BO_GT;
break;
2093 case BO_GE: Op = BO_LT;
break;
2103 Out <<
"not equal to ";
2110 Out << (shouldInvert ? LhsString : RhsString);
2112 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2113 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2114 if (shouldPrune.hasValue())
2115 event->setPrunable(shouldPrune.getValue());
2119 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
2120 StringRef LhsString,
const Expr *CondVarExpr,
const bool tookTrue,
2121 BugReporterContext &BRC, BugReport &report,
const ExplodedNode *N) {
2126 llvm::raw_svector_ostream Out(buf);
2127 Out <<
"Assuming " << LhsString <<
" is ";
2132 Out << (tookTrue ?
"not null" :
"null");
2134 Out << (tookTrue ?
"not nil" :
"nil");
2136 Out << (tookTrue ?
"true" :
"false");
2138 Out << (tookTrue ?
"non-zero" :
"zero");
2143 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2144 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2146 if (
const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
2147 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
2148 const ProgramState *
state = N->getState().get();
2149 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2150 if (report.isInteresting(R))
2151 event->setPrunable(
false);
2159 std::shared_ptr<PathDiagnosticPiece>
2160 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond,
const DeclRefExpr *DR,
2161 const bool tookTrue, BugReporterContext &BRC,
2162 BugReport &report,
const ExplodedNode *N) {
2168 llvm::raw_svector_ostream Out(Buf);
2170 Out <<
"Assuming '" << VD->getDeclName() <<
"' is ";
2175 Out << (tookTrue ?
"non-null" :
"null");
2177 Out << (tookTrue ?
"non-nil" :
"nil");
2179 Out << (tookTrue ?
"not equal to 0" :
"0");
2184 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2185 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2187 const ProgramState *
state = N->getState().get();
2188 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2189 if (report.isInteresting(R))
2190 event->setPrunable(
false);
2192 SVal V = state->getSVal(R);
2193 if (report.isInteresting(V))
2194 event->setPrunable(
false);
2197 return std::move(event);
2200 const char *
const ConditionBRVisitor::GenericTrueMessage =
2201 "Assuming the condition is true";
2202 const char *
const ConditionBRVisitor::GenericFalseMessage =
2203 "Assuming the condition is false";
2205 bool ConditionBRVisitor::isPieceMessageGeneric(
2206 const PathDiagnosticPiece *Piece) {
2207 return Piece->getString() == GenericTrueMessage ||
2208 Piece->getString() == GenericFalseMessage;
2211 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
2212 BugReporterContext &BRC,
const ExplodedNode *N, BugReport &BR) {
2216 const Decl *D = N->getLocationContext()->getDecl();
2223 if (Options.ShouldSuppressFromCXXStandardLibrary) {
2224 BR.markInvalid(getTag(),
nullptr);
2233 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2235 if (CD->
getName() ==
"list") {
2236 BR.markInvalid(getTag(),
nullptr);
2243 if (
const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2245 if (CD->
getName() ==
"__independent_bits_engine") {
2246 BR.markInvalid(getTag(),
nullptr);
2264 if (CD->
getName() ==
"basic_string") {
2265 BR.markInvalid(getTag(),
nullptr);
2272 if (CD->
getName() ==
"shared_ptr") {
2273 BR.markInvalid(getTag(),
nullptr);
2286 if (SM.
getFilename(Loc).endswith(
"sys/queue.h")) {
2287 BR.markInvalid(getTag(),
nullptr);
2293 std::shared_ptr<PathDiagnosticPiece>
2294 UndefOrNullArgVisitor::VisitNode(
const ExplodedNode *N,
2295 BugReporterContext &BRC, BugReport &BR) {
2306 CallEventRef<> Call = CEMgr.
getCaller(CEnter->getCalleeContext(),
State);
2310 for (
const auto ParamDecl : parms) {
2311 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2315 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2319 assert(ParamDecl &&
"Formal parameter has no decl?");
2334 SVal BoundVal = State->getSVal(R);
2335 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2336 BR.markInteresting(CEnter->getCalleeContext());
2343 std::shared_ptr<PathDiagnosticPiece>
2344 CXXSelfAssignmentBRVisitor::VisitNode(
const ExplodedNode *Succ,
2345 BugReporterContext &BRC, BugReport &) {
2350 if (!Edge.hasValue())
2353 auto Tag = Edge->
getTag();
2357 if (Tag->getTagDescription() !=
"cplusplus.SelfAssignment")
2363 dyn_cast<
CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());
2364 assert(Met &&
"Not a C++ method.");
2365 assert((Met->isCopyAssignmentOperator() || Met->isMoveAssignmentOperator()) &&
2366 "Not a copy/move assignment operator.");
2368 const auto *LCtx = Edge->getLocationContext();
2370 const auto &
State = Succ->getState();
2371 auto &SVB =
State->getStateManager().getSValBuilder();
2374 State->getSVal(
State->getRegion(Met->getParamDecl(0), LCtx));
2376 State->getSVal(SVB.getCXXThis(Met, LCtx->getStackFrame()));
2380 if (!L.isValid() || !L.asLocation().isValid())
2384 llvm::raw_svector_ostream Out(Buf);
2386 Out <<
"Assuming " << Met->getParamDecl(0)->getName() <<
2387 ((Param == This) ?
" == " :
" != ") <<
"*this";
2389 auto Piece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
2390 Piece->addRange(Met->getSourceRange());
2392 return std::move(Piece);
2395 std::shared_ptr<PathDiagnosticPiece>
2396 TaintBugVisitor::VisitNode(
const ExplodedNode *N,
2397 BugReporterContext &BRC, BugReport &) {
2400 if (!N->getState()->isTainted(V) || N->getFirstPred()->getState()->isTainted(V))
2408 PathDiagnosticLocation L =
2410 if (!L.isValid() || !L.asLocation().isValid())
2413 return std::make_shared<PathDiagnosticEventPiece>(L,
"Taint originated here");
2416 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
2417 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
2419 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
2420 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
2422 VisitNode(EndPathNode, BRC, BR);
2429 for (
const auto &I : Constraints) {
2431 auto RangeIt = I.second.begin();
2434 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2436 while ((++RangeIt) != I.second.end()) {
2437 Constraints = RefutationSolver->mkOr(
2439 RangeIt->From(), RangeIt->To(),
2443 RefutationSolver->addConstraint(Constraints);
2448 if (!isSat.hasValue())
2451 if (!isSat.getValue())
2452 BR.markInvalid(
"Infeasible constraints", EndPathNode->getLocationContext());
2455 std::shared_ptr<PathDiagnosticPiece>
2456 FalsePositiveRefutationBRVisitor::VisitNode(
const ExplodedNode *N,
2457 BugReporterContext &,
2461 ConstraintRangeTy::Factory &
CF =
2462 N->getState()->get_context<ConstraintRange>();
2465 for (
auto const &C : NewCs) {
2467 if (!Constraints.contains(Sym)) {
2468 Constraints = CF.add(Constraints, Sym, C.second);
2475 void FalsePositiveRefutationBRVisitor::Profile(
2476 llvm::FoldingSetNodeID &
ID)
const {
2478 ID.AddPointer(&Tag);
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Indicates that the tracked object is a CF object.
Defines the clang::ASTContext interface.
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
static StringRef getMacroName(SourceLocation Loc, BugReporterContext &BRC)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
static SMTExprRef getRangeExpr(SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
succ_iterator succ_begin()
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
const SymExpr * SymbolRef
Stmt - This represents one statement.
internal::Matcher< Stmt > StatementMatcher
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
C Language Family Type Representation.
Defines the SourceManager interface.
static bool isPointerToConst(const QualType &QT)
Decl - This represents one declaration (or definition), e.g.
Represents a point when we begin processing an inlined call.
Manages the lifetime of CallEvent objects.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintRangeTy
unsigned succ_size() const
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
const internal::VariadicDynCastAllOfMatcher< Stmt, BinaryOperator > binaryOperator
Matches binary operator expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, ObjCIvarRefExpr > objcIvarRefExpr
Matches a reference to an ObjCIvar.
Describes how types, statements, expressions, and declarations should be printed. ...
Represents a parameter to a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
bool isParentOf(const LocationContext *LC) const
Represents a struct/union/class.
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
Represents a program point after a store evaluation.
bool isReferenceType() const
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 isAssignmentOp() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Represents a point when we start the call exit sequence (for inlined call).
StringRef getOpcodeStr() const
static bool isInStdNamespace(const Decl *D)
Returns true if the root namespace of the given declaration is the 'std' C++ namespace.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const LocationContext * getParent() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest, const ExplodedNode *N, SVal ValueAfter)
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
static const Expr * peelOffPointerArithmetic(const BinaryOperator *B)
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static const MemRegion * getLocationRegionIfReference(const Expr *E, const ExplodedNode *N)
bool isScalarType() const
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
const Stmt * getCallSite() const
Represents a single basic block in a source-level CFG.
Represents a point when we finish the call exit sequence (for inlined call).
This represents one expression.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)
Gets an outside caller given a callee context.
bool inTopFrame() const override
Return true if the current LocationContext has no caller context.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
static std::pair< const ProgramPointTag *, const ProgramPointTag * > geteagerlyAssumeBinOpBifurcationTags()
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const ExpansionInfo & getExpansion() const
SourceLocation getEndLoc() const LLVM_READONLY
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isComparisonOp() const
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
Maps string IDs to AST nodes matched by parts of a matcher.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
CFGTerminator getTerminator()
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
QualType getCanonicalType() const
Encodes a location in the source.
static bool isCallStmt(const Stmt *S)
Returns true if this is a statement is a function or method call of some kind.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
ASTContext & getASTContext() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Represents a static or instance method of a struct/union/class.
bool isAnyPointerType() const
bool isObjCObjectPointerType() const
SMTSolverRef CreateZ3Solver()
Convenience method to create and Z3Solver object.
const ReturnStmt * getReturnStmt() const
static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os, const MemRegion *R, SVal V, const DeclStmt *DS)
Show diagnostics for initializing or declaring a region R with a bad value.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static StringRef getImmediateMacroNameForDiagnostics(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static bool isFunctionMacroExpansion(SourceLocation Loc, const SourceManager &SM)
ast_type_traits::DynTypedNode Node
Dataflow Directional Tag Classes.
static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os, const MemRegion *R, SVal V)
Show default diagnostics for storing bad region.
Parameter for Objective-C 'self' argument.
StmtClass getStmtClass() const
bool isBooleanType() const
const Decl * getSingleDecl() const
const ProgramPointTag * getTag() const
static void showBRParamDiagnostics(llvm::raw_svector_ostream &os, const VarRegion *VR, SVal V)
Display diagnostics for passing bad region as a parameter.
std::shared_ptr< SMTSolver > SMTSolverRef
Shared pointer for SMTSolvers.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
const LocationContext * getLocationContext() const
static bool isAdditiveOp(Opcode Opc)
const StackFrameContext * getStackFrame() const
Stores options for the analyzer from the command line.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
ObjCIvarRefExpr - A reference to an ObjC instance variable.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
ObjCIvarDecl - Represents an ObjC instance variable.
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR)
Returns true if N represents the DeclStmt declaring and initializing VR.
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
std::shared_ptr< SMTExpr > SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A reference to a declared variable, function, enum, etc.
bool isFunctionMacroExpansion() const
bool isPointerType() const
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
static bool isInterestingLValueExpr(const Expr *Ex)
Returns true if nodes for the given expression kind are always kept around.
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.