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();
166 const ExplodedNode *RightNode, SVal RightVal) {
167 if (LeftVal == RightVal)
170 const auto LLCV = LeftVal.getAs<nonloc::LazyCompoundVal>();
174 const auto RLCV = RightVal.getAs<nonloc::LazyCompoundVal>();
178 return LLCV->getRegion() == RLCV->getRegion() &&
179 LLCV->getStore() == LeftNode->getState()->getStore() &&
180 RLCV->getStore() == RightNode->getState()->getStore();
189 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(CondVarExpr)) {
190 if (
const auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl())) {
191 SVal DeclSVal = State->getSVal(State->getLValue(VD, LCtx));
192 if (
auto DeclCI = DeclSVal.getAs<nonloc::ConcreteInt>())
193 return &DeclCI->getValue();
202 BugReporterContext &BRC) {
205 BRC.getSourceManager(),
206 BRC.getASTContext().getLangOpts());
227 const ExplodedNode *N,
230 ProgramStateManager &Mgr = N->getState()->getStateManager();
237 if (
auto PS = N->getLocationAs<
PostStmt>())
239 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
240 N->getSVal(BO->getLHS()).getAsRegion()))
244 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
245 if (!Mgr.getSValBuilder()
246 .areEqual(State, ValueAtN, ValueAfter)
247 .isConstrainedTrue() &&
248 (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
258 std::shared_ptr<PathDiagnosticPiece>
259 BugReporterVisitor::getEndPath(BugReporterContext &,
260 const ExplodedNode *, BugReport &) {
265 BugReporterVisitor::finalizeVisitor(BugReporterContext &,
266 const ExplodedNode *, BugReport &) {}
268 std::shared_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
269 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
270 PathDiagnosticLocation L =
273 const auto &Ranges = BR.getRanges();
277 auto P = std::make_shared<PathDiagnosticEventPiece>(
278 L, BR.getDescription(), Ranges.begin() == Ranges.end());
296 const SubRegion *RegionOfInterest;
297 MemRegionManager &MmrMgr;
304 static const unsigned DEREFERENCE_LIMIT = 2;
314 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
315 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
320 NoStoreFuncVisitor(
const SubRegion *R)
321 : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
322 SM(MmrMgr.getContext().getSourceManager()),
323 PP(MmrMgr.getContext().getPrintingPolicy()) {}
325 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
328 ID.AddPointer(RegionOfInterest);
331 void *getTag()
const {
333 return static_cast<void *
>(&Tag);
336 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
337 BugReporterContext &BR,
338 BugReport &R)
override;
349 const MemRegion *R,
const RegionVector &Vec = {},
355 bool isRegionOfInterestModifiedInFrame(
const ExplodedNode *N) {
358 if (!FramesModifyingCalculated.count(SCtx))
359 findModifyingFrames(N);
360 return FramesModifyingRegion.count(SCtx);
365 void findModifyingFrames(
const ExplodedNode *N);
371 std::shared_ptr<PathDiagnosticPiece>
372 maybeEmitNote(BugReport &R,
const CallEvent &Call,
const ExplodedNode *N,
373 const RegionVector &FieldChain,
const MemRegion *MatchedRegion,
374 StringRef FirstElement,
bool FirstIsReferenceType,
375 unsigned IndirectionLevel);
379 bool prettyPrintRegionName(StringRef FirstElement,
bool FirstIsReferenceType,
380 const MemRegion *MatchedRegion,
381 const RegionVector &FieldChain,
382 int IndirectionLevel,
383 llvm::raw_svector_ostream &os);
386 static StringRef prettyPrintFirstElement(StringRef FirstElement,
387 bool MoreItemsExpected,
388 int IndirectionLevel,
389 llvm::raw_svector_ostream &os);
399 const char *IvarBind =
"Ivar";
400 if (!Parent || !Parent->
hasBody())
403 hasOperatorName(
"="),
404 hasLHS(ignoringParenImpCasts(
410 if (IvarRef->isFreeIvar())
413 const Expr *
Base = IvarRef->getBase();
414 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
415 Base = ICE->getSubExpr();
417 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Base))
418 if (
const auto *
ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
431 RuntimeDefinition RD = Call->getRuntimeDefinition();
432 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
433 return FD->parameters();
434 if (
const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
435 return MD->parameters();
437 return Call->parameters();
453 NoStoreFuncVisitor::findRegionOfInterestInRecord(
458 if (depth == DEREFERENCE_LIMIT)
461 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
462 if (!RDX->hasDefinition())
467 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
468 for (
const auto II : RDX->bases())
469 if (
const RecordDecl *RRD = II.getType()->getAsRecordDecl())
471 findRegionOfInterestInRecord(RRD,
State, R, Vec, depth))
476 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
477 const SVal
V =
State->getSVal(FR);
478 const MemRegion *VR = V.getAsRegion();
480 RegionVector VecF = Vec;
483 if (RegionOfInterest == VR)
488 findRegionOfInterestInRecord(RRD,
State, FR, VecF, depth + 1))
497 findRegionOfInterestInRecord(RRD,
State, VR, VecF, depth + 1))
504 std::shared_ptr<PathDiagnosticPiece>
505 NoStoreFuncVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BR,
514 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
517 CallEventRef<> Call =
518 BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
522 if (
const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
523 if (
const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
524 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
525 if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
528 return maybeEmitNote(R, *Call, N, {}, SelfRegion,
"self",
533 if (
const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
534 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
535 if (RegionOfInterest->isSubRegionOf(ThisR) &&
536 !CCall->getDecl()->isImplicit())
537 return maybeEmitNote(R, *Call, N, {}, ThisR,
"this",
546 for (
unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
548 SVal
V = Call->getArgSVal(I);
552 int IndirectionLevel = 1;
554 while (
const MemRegion *MR = V.getAsRegion()) {
556 return maybeEmitNote(R, *Call, N, {}, MR, ParamName,
557 ParamIsReferenceType, IndirectionLevel);
565 findRegionOfInterestInRecord(RD, State, MR))
566 return maybeEmitNote(R, *Call, N, *
P, RegionOfInterest, ParamName,
567 ParamIsReferenceType, IndirectionLevel);
569 V = State->getSVal(MR, PT);
578 void NoStoreFuncVisitor::findModifyingFrames(
const ExplodedNode *N) {
581 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
589 LastReturnState =
State;
590 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
593 FramesModifyingCalculated.insert(N->getLocationContext()->getStackFrame());
598 auto p = FramesModifyingRegion.insert(SCtx);
606 if (
auto CE = N->getLocationAs<
CallEnter>())
607 if (CE->getCalleeContext() == OriginalSCtx)
610 N = N->getFirstPred();
614 std::shared_ptr<PathDiagnosticPiece> NoStoreFuncVisitor::maybeEmitNote(
615 BugReport &R,
const CallEvent &Call,
const ExplodedNode *N,
616 const RegionVector &FieldChain,
const MemRegion *MatchedRegion,
617 StringRef FirstElement,
bool FirstIsReferenceType,
618 unsigned IndirectionLevel) {
628 if (Call.isInSystemHeader()) {
636 if (!N->getStackFrame()->getCFG()->isLinear())
637 R.markInvalid(getTag(),
nullptr);
641 PathDiagnosticLocation L =
647 if (!L.hasValidLocation())
651 llvm::raw_svector_ostream os(sbuf);
652 os <<
"Returning without writing to '";
655 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType, MatchedRegion,
656 FieldChain, IndirectionLevel, os))
660 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
663 bool NoStoreFuncVisitor::prettyPrintRegionName(StringRef FirstElement,
664 bool FirstIsReferenceType,
665 const MemRegion *MatchedRegion,
666 const RegionVector &FieldChain,
667 int IndirectionLevel,
668 llvm::raw_svector_ostream &os) {
670 if (FirstIsReferenceType)
673 RegionVector RegionSequence;
676 assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
677 const MemRegion *R = RegionOfInterest;
678 while (R != MatchedRegion) {
679 RegionSequence.push_back(R);
680 R = cast<SubRegion>(R)->getSuperRegion();
682 std::reverse(RegionSequence.begin(), RegionSequence.end());
683 RegionSequence.append(FieldChain.begin(), FieldChain.end());
686 for (
const MemRegion *R : RegionSequence) {
690 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
694 Sep = prettyPrintFirstElement(FirstElement,
696 IndirectionLevel, os);
701 if (!isa<DeclRegion>(R))
704 const auto *DR = cast<DeclRegion>(R);
705 Sep = DR->getValueType()->isAnyPointerType() ?
"->" :
".";
706 DR->getDecl()->getDeclName().print(os, PP);
710 prettyPrintFirstElement(FirstElement,
711 false, IndirectionLevel, os);
715 StringRef NoStoreFuncVisitor::prettyPrintFirstElement(
716 StringRef FirstElement,
bool MoreItemsExpected,
int IndirectionLevel,
717 llvm::raw_svector_ostream &os) {
720 if (IndirectionLevel > 0 && MoreItemsExpected) {
725 if (IndirectionLevel > 0 && MoreItemsExpected)
728 for (
int i = 0;
i < IndirectionLevel;
i++)
732 if (IndirectionLevel > 0 && MoreItemsExpected)
747 const SubRegion *RegionOfInterest;
748 const SVal ValueAtDereference;
752 bool WasModified =
false;
755 MacroNullReturnSuppressionVisitor(
const SubRegion *R,
756 const SVal
V) : RegionOfInterest(R),
757 ValueAtDereference(V) {}
759 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
760 BugReporterContext &BRC,
761 BugReport &BR)
override {
765 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
770 if (
auto Loc = matchAssignment(N)) {
775 BR.markInvalid(getTag(), MacroName.c_str());
785 static void addMacroVisitorIfNecessary(
786 const ExplodedNode *N,
const MemRegion *R,
787 bool EnableNullFPSuppression, BugReport &BR,
789 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
790 if (EnableNullFPSuppression &&
791 Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
792 BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
793 R->getAs<SubRegion>(), V));
796 void* getTag()
const {
798 return static_cast<void *
>(&Tag);
801 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
802 ID.AddPointer(getTag());
811 auto *LCtx = N->getLocationContext();
815 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
816 if (
const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
817 if (
const Expr *RHS = VD->getInit())
818 if (RegionOfInterest->isSubRegionOf(
819 State->getLValue(VD, LCtx).getAsRegion()))
820 return RHS->getBeginLoc();
821 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(S)) {
822 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
823 const Expr *RHS = BO->getRHS();
824 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
851 bool EnableNullFPSuppression;
852 bool ShouldInvalidate =
true;
859 : StackFrame(Frame), EnableNullFPSuppression(Suppressed),
862 static void *getTag() {
864 return static_cast<void *
>(&Tag);
867 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
868 ID.AddPointer(ReturnVisitor::getTag());
869 ID.AddPointer(StackFrame);
870 ID.AddBoolean(EnableNullFPSuppression);
880 static void addVisitorIfNecessary(
const ExplodedNode *
Node,
const Stmt *S,
882 bool InEnableNullFPSuppression) {
890 const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S);
898 if (CEE->getCalleeContext()->getCallSite() == S)
902 Node = Node->getFirstPred();
911 if (!BypassCXXNewExprEval)
914 if (SP->getStmt() == S && CurrentSFC == PredSFC)
917 CurrentSFC = PredSFC;
918 }
while (Node->getStackFrame() == CurrentSFC);
921 while (Node && Node->getLocation().getAs<
PostStmt>())
922 Node = Node->getFirstPred();
937 SVal RetVal = Node->getSVal(S);
940 if (cast<Expr>(S)->isGLValue())
942 RetVal = State->getSVal(*LValue);
947 bool EnableNullFPSuppression =
false;
948 if (InEnableNullFPSuppression &&
949 Options.ShouldSuppressNullReturnPaths)
951 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
953 BR.markInteresting(CalleeContext);
954 BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
955 EnableNullFPSuppression,
959 std::shared_ptr<PathDiagnosticPiece>
960 visitNodeInitial(
const ExplodedNode *N,
961 BugReporterContext &BRC, BugReport &BR) {
963 if (N->getLocationContext() != StackFrame)
970 const auto *Ret = dyn_cast<
ReturnStmt>(SP->getStmt());
977 SVal
V = State->getSVal(Ret, StackFrame);
978 if (V.isUnknownOrUndef())
984 const Expr *RetE = Ret->getRetValue();
985 assert(RetE &&
"Tracking a return value for a void function");
990 if ((LValue = V.getAs<Loc>())) {
991 SVal RValue = State->getRawSVal(*LValue, RetE->
getType());
992 if (RValue.getAs<DefinedSVal>())
998 if (V.getAs<nonloc::LazyCompoundVal>() ||
999 V.getAs<nonloc::CompoundVal>())
1005 bugreporter::trackExpressionValue(N, RetE, BR, EnableNullFPSuppression);
1009 llvm::raw_svector_ostream Out(Msg);
1011 if (State->isNull(V).isConstrainedTrue()) {
1012 if (V.getAs<Loc>()) {
1017 if (EnableNullFPSuppression &&
1018 Options.ShouldAvoidSuppressingNullArgumentPaths)
1019 Mode = MaybeUnsuppress;
1022 Out <<
"Returning nil";
1024 Out <<
"Returning null pointer";
1027 Out <<
"Returning zero";
1031 if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1032 Out <<
"Returning the value " << CI->getValue();
1033 }
else if (V.getAs<Loc>()) {
1034 Out <<
"Returning pointer";
1036 Out <<
"Returning value";
1041 if (
const MemRegion *MR = LValue->getAsRegion()) {
1042 if (MR->canPrintPretty()) {
1043 Out <<
" (reference to ";
1044 MR->printPretty(Out);
1050 if (
const auto *DR = dyn_cast<DeclRefExpr>(RetE))
1051 if (
const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
1052 Out <<
" (loaded from '" << *DD <<
"')";
1055 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
1056 if (!L.isValid() || !L.asLocation().isValid())
1059 return std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
1062 std::shared_ptr<PathDiagnosticPiece>
1063 visitNodeMaybeUnsuppress(
const ExplodedNode *N,
1064 BugReporterContext &BRC, BugReport &BR) {
1066 assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
1074 if (CE->getCalleeContext() != StackFrame)
1082 ProgramStateManager &StateMgr = BRC.getStateManager();
1086 CallEventRef<> Call = CallMgr.
getCaller(StackFrame, State);
1087 for (
unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
1092 const Expr *ArgE = Call->getArgExpr(I);
1097 if (!State->isNull(*ArgV).isConstrainedTrue())
1100 if (bugreporter::trackExpressionValue(N, ArgE, BR, EnableNullFPSuppression))
1101 ShouldInvalidate =
false;
1111 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
1112 BugReporterContext &BRC,
1113 BugReport &BR)
override {
1116 return visitNodeInitial(N, BRC, BR);
1117 case MaybeUnsuppress:
1118 return visitNodeMaybeUnsuppress(N, BRC, BR);
1123 llvm_unreachable(
"Invalid visit mode!");
1126 void finalizeVisitor(BugReporterContext &,
const ExplodedNode *,
1127 BugReport &BR)
override {
1128 if (EnableNullFPSuppression && ShouldInvalidate)
1129 BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
1139 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1141 ID.AddPointer(&tag);
1144 ID.AddBoolean(EnableNullFPSuppression);
1161 const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1162 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1167 assert(VR->getDecl()->isStaticLocal() &&
"non-static stackless VarRegion");
1171 assert(VR->getDecl()->hasLocalStorage());
1178 const MemRegion *R, SVal
V,
const DeclStmt *DS) {
1179 if (R->canPrintPretty()) {
1184 if (V.getAs<loc::ConcreteInt>()) {
1186 if (R->isBoundable()) {
1187 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1188 if (TR->getValueType()->isObjCObjectPointerType()) {
1189 os << action <<
"nil";
1195 os << action <<
"a null pointer value";
1197 }
else if (
auto CVal = V.getAs<nonloc::ConcreteInt>()) {
1198 os << action << CVal->getValue();
1201 if (isa<VarRegion>(R)) {
1203 if (VD->getInit()) {
1204 os << (R->canPrintPretty() ?
"initialized" :
"Initializing")
1205 <<
" to a garbage value";
1207 os << (R->canPrintPretty() ?
"declared" :
"Declaring")
1208 <<
" without an initial value";
1212 os << (R->canPrintPretty() ?
"initialized" :
"Initialized")
1220 const VarRegion *VR,
1222 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1226 if (V.getAs<loc::ConcreteInt>()) {
1227 if (Param->getType()->isObjCObjectPointerType())
1228 os <<
"nil object reference";
1230 os <<
"null pointer value";
1231 }
else if (V.isUndef()) {
1232 os <<
"uninitialized value";
1233 }
else if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1234 os <<
"the value " << CI->getValue();
1240 unsigned Idx = Param->getFunctionScopeIndex() + 1;
1241 os <<
" via " << Idx << llvm::getOrdinalSuffix(Idx) <<
" parameter";
1242 if (VR->canPrintPretty()) {
1244 VR->printPretty(os);
1252 if (V.getAs<loc::ConcreteInt>()) {
1254 if (R->isBoundable()) {
1255 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1256 if (TR->getValueType()->isObjCObjectPointerType()) {
1257 os <<
"nil object reference stored";
1263 if (R->canPrintPretty())
1264 os <<
"Null pointer value stored";
1266 os <<
"Storing null pointer value";
1269 }
else if (V.isUndef()) {
1270 if (R->canPrintPretty())
1271 os <<
"Uninitialized value stored";
1273 os <<
"Storing uninitialized value";
1275 }
else if (
auto CV = V.getAs<nonloc::ConcreteInt>()) {
1276 if (R->canPrintPretty())
1277 os <<
"The value " << CV->getValue() <<
" is assigned";
1279 os <<
"Assigning " << CV->getValue();
1282 if (R->canPrintPretty())
1283 os <<
"Value assigned";
1285 os <<
"Assigning value";
1288 if (R->canPrintPretty()) {
1294 std::shared_ptr<PathDiagnosticPiece>
1295 FindLastStoreBRVisitor::VisitNode(
const ExplodedNode *Succ,
1296 BugReporterContext &BRC, BugReport &BR) {
1300 const ExplodedNode *StoreSite =
nullptr;
1301 const ExplodedNode *Pred = Succ->getFirstPred();
1302 const Expr *InitE =
nullptr;
1303 bool IsParam =
false;
1306 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1309 InitE = VR->getDecl()->getInit();
1316 const MemRegion *FieldReg = (
const MemRegion *)PIP->getLocationValue();
1317 if (FieldReg && FieldReg == R) {
1319 InitE = PIP->getInitializer()->getInit();
1329 if (Succ->getState()->getSVal(R) !=
V)
1334 if (!PS || PS->getLocationValue() != R)
1344 if (BO->isAssignmentOp())
1345 InitE = BO->getRHS();
1352 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1354 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1356 ProgramStateManager &StateMgr = BRC.getStateManager();
1359 CallEventRef<> Call = CallMgr.
getCaller(CE->getCalleeContext(),
1361 InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1368 if (
const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1369 InitE = TmpR->getExpr();
1380 V.getAs<loc::ConcreteInt>() ||
V.getAs<nonloc::ConcreteInt>()) {
1383 bugreporter::trackExpressionValue(StoreSite, InitE, BR,
1384 EnableNullFPSuppression);
1387 BR, EnableNullFPSuppression);
1392 llvm::raw_svector_ostream os(sbuf);
1395 const Stmt *S = PS->getStmt();
1396 const char *action =
nullptr;
1397 const auto *DS = dyn_cast<
DeclStmt>(S);
1398 const auto *VR = dyn_cast<VarRegion>(R);
1401 action = R->canPrintPretty() ?
"initialized to " :
1403 }
else if (isa<BlockExpr>(S)) {
1404 action = R->canPrintPretty() ?
"captured by block as " :
1405 "Captured by block as ";
1409 SVal
V = StoreSite->getSVal(S);
1410 if (
const auto *BDR =
1411 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1412 if (
const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1413 if (
auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
1414 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1415 *KV, OriginalR, EnableNullFPSuppression));
1423 }
else if (StoreSite->getLocation().getAs<
CallEnter>()) {
1424 if (
const auto *VR = dyn_cast<VarRegion>(R))
1428 if (os.str().empty())
1433 PathDiagnosticLocation L;
1435 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
1438 if (!L.isValid() || !L.asLocation().isValid())
1441 if (!L.isValid() || !L.asLocation().isValid())
1444 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1451 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1453 ID.AddPointer(&tag);
1454 ID.AddBoolean(Assumption);
1460 const char *TrackConstraintBRVisitor::getTag() {
1461 return "TrackConstraintBRVisitor";
1464 bool TrackConstraintBRVisitor::isUnderconstrained(
const ExplodedNode *N)
const {
1466 return N->getState()->isNull(Constraint).isUnderconstrained();
1467 return (
bool)N->getState()->assume(Constraint, !Assumption);
1470 std::shared_ptr<PathDiagnosticPiece>
1471 TrackConstraintBRVisitor::VisitNode(
const ExplodedNode *N,
1472 BugReporterContext &BRC, BugReport &) {
1473 const ExplodedNode *PrevN = N->getFirstPred();
1479 if (!IsTrackingTurnedOn)
1480 if (!isUnderconstrained(N))
1481 IsTrackingTurnedOn =
true;
1482 if (!IsTrackingTurnedOn)
1487 if (isUnderconstrained(PrevN)) {
1493 assert(!isUnderconstrained(N));
1498 llvm::raw_svector_ostream os(sbuf);
1500 if (Constraint.getAs<Loc>()) {
1501 os <<
"Assuming pointer value is ";
1502 os << (Assumption ?
"non-null" :
"null");
1505 if (os.str().empty())
1510 PathDiagnosticLocation L =
1515 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1516 X->setTag(getTag());
1517 return std::move(
X);
1527 SuppressInlineDefensiveChecksVisitor::
1528 SuppressInlineDefensiveChecksVisitor(DefinedSVal
Value,
const ExplodedNode *N)
1531 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1532 if (!Options.ShouldSuppressInlinedDefensiveChecks)
1535 assert(N->getState()->isNull(
V).isConstrainedTrue() &&
1536 "The visitor only tracks the cases where V is constrained to 0");
1539 void SuppressInlineDefensiveChecksVisitor::Profile(
1540 llvm::FoldingSetNodeID &
ID)
const {
1546 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1547 return "IDCVisitor";
1550 std::shared_ptr<PathDiagnosticPiece>
1551 SuppressInlineDefensiveChecksVisitor::VisitNode(
const ExplodedNode *Succ,
1552 BugReporterContext &BRC,
1554 const ExplodedNode *Pred = Succ->getFirstPred();
1559 if (!IsTrackingTurnedOn)
1560 if (Succ->getState()->isNull(
V).isConstrainedTrue())
1561 IsTrackingTurnedOn =
true;
1562 if (!IsTrackingTurnedOn)
1567 if (!Pred->getState()->isNull(
V).isConstrainedTrue()) {
1570 assert(Succ->getState()->isNull(
V).isConstrainedTrue());
1574 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1575 if (CurLC != ReportLC && !CurLC->
isParentOf(ReportLC)) {
1576 BR.markInvalid(
"Suppress IDC", CurLC);
1584 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
1590 const Stmt *CurTerminatorStmt =
nullptr;
1592 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1594 const Stmt *CurStmt = SP->getStmt();
1598 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1604 if (!CurTerminatorStmt)
1614 BR.markInvalid(
"Suppress Macro IDC", CurLC);
1639 const ExplodedNode *Origin;
1641 llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
1644 TrackControlDependencyCondBRVisitor(
const ExplodedNode *O)
1645 : Origin(O), ControlDeps(&O->getCFG()) {}
1647 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
1652 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
1653 BugReporterContext &BRC,
1654 BugReport &BR)
override;
1659 if (
auto SP = Node->getLocationAs<
StmtPoint>()) {
1660 const Stmt *S = SP->getStmt();
1663 return const_cast<CFGBlock *
>(Node->getLocationContext()
1664 ->getAnalysisDeclContext()->getCFGStmtMap()->getBlock(S));
1670 static std::shared_ptr<PathDiagnosticEventPiece>
1672 const ExplodedNode *N,
1673 BugReporterContext &BRC) {
1675 if (BRC.getAnalyzerOptions().AnalysisDiagOpt ==
PD_NONE ||
1676 !BRC.getAnalyzerOptions().ShouldTrackConditionsDebug)
1681 BRC.getSourceManager(),
1682 BRC.getASTContext().getLangOpts());
1684 return std::make_shared<PathDiagnosticEventPiece>(
1686 Cond, BRC.getSourceManager(), N->getLocationContext()),
1687 (Twine() +
"Tracking condition '" + ConditionText +
"'").str());
1690 std::shared_ptr<PathDiagnosticPiece>
1691 TrackControlDependencyCondBRVisitor::VisitNode(
const ExplodedNode *N,
1692 BugReporterContext &BRC,
1695 if (Origin->getStackFrame() != N->getStackFrame())
1701 if (!VisitedBlocks.insert(NB).second)
1707 if (!OriginB || !NB)
1710 if (ControlDeps.isControlDependent(OriginB, NB)) {
1715 if (BR.addTrackedCondition(N)) {
1716 bugreporter::trackExpressionValue(
1717 N, Condition, BR,
false);
1731 const ExplodedNode *N) {
1732 if (
const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1733 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1734 if (!VD->getType()->isReferenceType())
1736 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1737 MemRegionManager &MRMgr = StateMgr.getRegionManager();
1738 return MRMgr.getVarRegion(VD, N->getLocationContext());
1753 static const Expr *peelOffOuterExpr(
const Expr *Ex,
1754 const ExplodedNode *N) {
1756 if (
const auto *FE = dyn_cast<FullExpr>(Ex))
1757 return peelOffOuterExpr(FE->getSubExpr(), N);
1758 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1759 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1760 if (
const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1762 if (PropRef && PropRef->isMessagingGetter()) {
1763 const Expr *GetterMessageSend =
1764 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1766 return peelOffOuterExpr(GetterMessageSend, N);
1771 if (
const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1774 const ExplodedNode *NI = N;
1778 const CFGBlock *srcBlk = BE->getSrc();
1781 bool TookTrueBranch = (*(srcBlk->
succ_begin()) == BE->getDst());
1783 return peelOffOuterExpr(CO->getTrueExpr(), N);
1785 return peelOffOuterExpr(CO->getFalseExpr(), N);
1789 NI = NI->getFirstPred();
1793 if (
auto *BO = dyn_cast<BinaryOperator>(Ex))
1795 return peelOffOuterExpr(SubEx, N);
1797 if (
auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1798 if (UO->getOpcode() == UO_LNot)
1799 return peelOffOuterExpr(UO->getSubExpr(), N);
1809 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1810 if (
const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1811 return peelOffOuterExpr(DerefEx, N);
1819 static const ExplodedNode* findNodeForExpression(
const ExplodedNode *N,
1820 const Expr *Inner) {
1824 N = N->getFirstPred();
1829 bool bugreporter::trackExpressionValue(
const ExplodedNode *InputNode,
1830 const Expr *E, BugReport &report,
1831 bool EnableNullFPSuppression) {
1832 if (!E || !InputNode)
1835 const Expr *Inner = peelOffOuterExpr(E, InputNode);
1836 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1847 if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions)
1848 report.addVisitor(llvm::make_unique<TrackControlDependencyCondBRVisitor>(
1854 if (
const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1855 trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression);
1858 if (
const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
1859 trackExpressionValue(
1860 LVNode, Arr->getIdx(), report,
false);
1865 SVal LVal = LVNode->getSVal(Inner);
1868 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
1873 if (RR && !LVIsNull)
1874 if (
auto KV = LVal.getAs<KnownSVal>())
1875 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1876 *KV, RR, EnableNullFPSuppression));
1882 const MemRegion *R = (RR && LVIsNull) ? RR :
1883 LVNode->getSVal(Inner).getAsRegion();
1888 SVal
V = LVState->getRawSVal(loc::MemRegionVal(R));
1890 llvm::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R)));
1892 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
1893 LVNode, R, EnableNullFPSuppression, report, V);
1895 report.markInteresting(V);
1896 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1899 if (V.getAsLocSymbol(
true))
1900 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1901 V.castAs<DefinedSVal>(),
false));
1904 if (
auto DV = V.getAs<DefinedSVal>())
1905 if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1906 EnableNullFPSuppression)
1908 llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1911 if (
auto KV = V.getAs<KnownSVal>())
1912 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1913 *KV, R, EnableNullFPSuppression));
1920 SVal
V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
1922 ReturnVisitor::addVisitorIfNecessary(
1923 LVNode, Inner, report, EnableNullFPSuppression);
1926 if (
auto L = V.getAs<loc::MemRegionVal>()) {
1927 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1933 bool CanDereference =
true;
1934 if (
const auto *SR = dyn_cast<SymbolicRegion>(L->getRegion()))
1935 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
1936 CanDereference =
false;
1943 RVal = LVState->getRawSVal(L.getValue(), Inner->
getType());
1944 }
else if (CanDereference) {
1945 RVal = LVState->getSVal(L->getRegion());
1949 if (
auto KV = RVal.getAs<KnownSVal>())
1950 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1951 *KV, L->getRegion(), EnableNullFPSuppression));
1953 const MemRegion *RegionRVal = RVal.getAsRegion();
1954 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1955 report.markInteresting(RegionRVal);
1956 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1957 loc::MemRegionVal(RegionRVal),
false));
1967 const Expr *NilReceiverBRVisitor::getNilReceiver(
const Stmt *S,
1968 const ExplodedNode *N) {
1972 if (
const Expr *Receiver = ME->getInstanceReceiver()) {
1974 SVal
V = N->getSVal(Receiver);
1975 if (state->isNull(V).isConstrainedTrue())
1981 std::shared_ptr<PathDiagnosticPiece>
1982 NilReceiverBRVisitor::VisitNode(
const ExplodedNode *N,
1983 BugReporterContext &BRC, BugReport &BR) {
1988 const Stmt *S = P->getStmt();
1989 const Expr *Receiver = getNilReceiver(S, N);
1994 llvm::raw_svector_ostream
OS(Buf);
1996 if (
const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
1998 ME->getSelector().print(OS);
1999 OS <<
"' not called";
2002 OS <<
"No method is called";
2004 OS <<
" because the receiver is nil";
2009 bugreporter::trackExpressionValue(N, Receiver, BR,
2012 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
2013 N->getLocationContext());
2014 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
2022 void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
2024 bool EnableNullFPSuppression) {
2025 const ExplodedNode *N = BR.getErrorNode();
2026 std::deque<const Stmt *> WorkList;
2027 WorkList.push_back(S);
2029 while (!WorkList.empty()) {
2030 const Stmt *Head = WorkList.front();
2031 WorkList.pop_front();
2033 ProgramStateManager &StateMgr = N->getState()->getStateManager();
2035 if (
const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
2036 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
2037 const VarRegion *R =
2038 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
2041 SVal
V = N->getSVal(S);
2043 if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
2045 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
2046 V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
2052 WorkList.push_back(SubStmt);
2062 const char *ConditionBRVisitor::getTag() {
2063 return "ConditionBRVisitor";
2066 std::shared_ptr<PathDiagnosticPiece>
2067 ConditionBRVisitor::VisitNode(
const ExplodedNode *N,
2068 BugReporterContext &BRC, BugReport &BR) {
2069 auto piece = VisitNodeImpl(N, BRC, BR);
2071 piece->setTag(getTag());
2072 if (
auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
2073 ev->setPrunable(
true,
false);
2078 std::shared_ptr<PathDiagnosticPiece>
2079 ConditionBRVisitor::VisitNodeImpl(
const ExplodedNode *N,
2080 BugReporterContext &BRC, BugReport &BR) {
2082 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
2088 const CFGBlock *SrcBlock = BE->getSrc();
2095 N->getFirstPred()->getLocation().getTag();
2096 if (PreviousNodeTag == Tags.first || PreviousNodeTag == Tags.second)
2099 return VisitTerminator(Term, N, SrcBlock, BE->getDst(), BR, BRC);
2106 if (CurrentNodeTag != Tags.first && CurrentNodeTag != Tags.second)
2109 bool TookTrue = CurrentNodeTag == Tags.first;
2110 return VisitTrueTest(cast<Expr>(PS->getStmt()), BRC, BR, N, TookTrue);
2116 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTerminator(
2117 const Stmt *Term,
const ExplodedNode *N,
const CFGBlock *srcBlk,
2118 const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
2119 const Expr *Cond =
nullptr;
2139 case Stmt::IfStmtClass:
2140 Cond = cast<IfStmt>(Term)->getCond();
2142 case Stmt::ConditionalOperatorClass:
2143 Cond = cast<ConditionalOperator>(Term)->getCond();
2145 case Stmt::BinaryOperatorClass:
2149 const auto *BO = cast<BinaryOperator>(Term);
2150 assert(BO->isLogicalOp() &&
2151 "CFG terminator is not a short-circuit operator!");
2152 Cond = BO->getLHS();
2161 while (
const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
2162 if (!InnerBO->isLogicalOp())
2169 const bool TookTrue = *(srcBlk->
succ_begin()) == dstBlk;
2170 return VisitTrueTest(Cond, BRC, R, N, TookTrue);
2173 std::shared_ptr<PathDiagnosticPiece>
2174 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond, BugReporterContext &BRC,
2175 BugReport &R,
const ExplodedNode *N,
2186 !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
2187 CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
2191 const Expr *CondTmp = Cond;
2192 bool TookTrueTmp = TookTrue;
2199 case Stmt::BinaryOperatorClass:
2200 if (
auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
2201 BRC, R, N, TookTrueTmp, IsAssuming))
2204 case Stmt::DeclRefExprClass:
2205 if (
auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
2206 BRC, R, N, TookTrueTmp, IsAssuming))
2209 case Stmt::MemberExprClass:
2210 if (
auto P = VisitTrueTest(Cond, cast<MemberExpr>(CondTmp),
2211 BRC, R, N, TookTrueTmp, IsAssuming))
2214 case Stmt::UnaryOperatorClass: {
2215 const auto *UO = cast<UnaryOperator>(CondTmp);
2216 if (UO->getOpcode() == UO_LNot) {
2217 TookTrueTmp = !TookTrueTmp;
2218 CondTmp = UO->getSubExpr();
2234 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2235 if (!Loc.isValid() || !Loc.asLocation().isValid())
2238 return std::make_shared<PathDiagnosticEventPiece>(
2239 Loc, TookTrue ? GenericTrueMessage : GenericFalseMessage);
2242 bool ConditionBRVisitor::patternMatch(
const Expr *Ex,
2243 const Expr *ParentEx,
2245 BugReporterContext &BRC,
2247 const ExplodedNode *N,
2249 bool IsSameFieldName) {
2250 const Expr *OriginalExpr = Ex;
2253 if (isa<GNUNullExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
2254 isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) ||
2255 isa<FloatingLiteral>(Ex)) {
2262 const LangOptions &LO = BRC.getASTContext().getLangOpts();
2272 if (
const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2273 const bool quotes = isa<VarDecl>(DR->getDecl());
2277 const ProgramState *
state = N->getState().get();
2278 if (
const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2279 LCtx).getAsRegion()) {
2280 if (report.isInteresting(R))
2283 const ProgramState *state = N->getState().get();
2284 SVal
V = state->getSVal(R);
2285 if (report.isInteresting(V))
2290 Out << DR->getDecl()->getDeclName().getAsString();
2296 if (
const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2299 if (IL->getValue() == 0) {
2305 if (IL->getValue() == 0) {
2311 Out << IL->getValue();
2315 if (
const auto *ME = dyn_cast<MemberExpr>(Ex)) {
2316 if (!IsSameFieldName)
2317 Out <<
"field '" << ME->getMemberDecl()->getName() <<
'\'';
2322 BRC.getSourceManager(), BRC.getASTContext().getLangOpts(), 0)
2329 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTrueTest(
2331 BugReport &R,
const ExplodedNode *N,
bool TookTrue,
bool IsAssuming) {
2332 bool shouldInvert =
false;
2337 bool IsSameFieldName =
false;
2338 if (
const auto *LhsME =
2340 if (
const auto *RhsME =
2342 IsSameFieldName = LhsME->getMemberDecl()->getName() ==
2343 RhsME->getMemberDecl()->getName();
2347 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2348 const bool isVarLHS = patternMatch(BExpr->
getLHS(), BExpr, OutLHS, BRC, R,
2349 N, shouldPrune, IsSameFieldName);
2350 const bool isVarRHS = patternMatch(BExpr->
getRHS(), BExpr, OutRHS, BRC, R,
2351 N, shouldPrune, IsSameFieldName);
2353 shouldInvert = !isVarLHS && isVarRHS;
2361 return VisitConditionVariable(LhsString, BExpr->
getLHS(), BRC, R, N,
2367 if (LhsString.empty() || RhsString.empty() ||
2373 llvm::raw_svector_ostream Out(buf);
2374 Out << (IsAssuming ?
"Assuming " :
"")
2375 << (shouldInvert ? RhsString : LhsString) <<
" is ";
2381 case BO_LT: Op = BO_GT;
break;
2382 case BO_GT: Op = BO_LT;
break;
2383 case BO_LE: Op = BO_GE;
break;
2384 case BO_GE: Op = BO_LE;
break;
2389 case BO_EQ: Op = BO_NE;
break;
2390 case BO_NE: Op = BO_EQ;
break;
2391 case BO_LT: Op = BO_GE;
break;
2392 case BO_GT: Op = BO_LE;
break;
2393 case BO_LE: Op = BO_GT;
break;
2394 case BO_GE: Op = BO_LT;
break;
2404 Out <<
"not equal to ";
2411 Out << (shouldInvert ? LhsString : RhsString);
2413 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2416 std::string Message = Out.str();
2417 Message[0] = toupper(Message[0]);
2421 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
2423 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
2424 if (shouldPrune.hasValue())
2425 event->setPrunable(shouldPrune.getValue());
2429 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
2430 StringRef LhsString,
const Expr *CondVarExpr, BugReporterContext &BRC,
2431 BugReport &report,
const ExplodedNode *N,
bool TookTrue) {
2436 llvm::raw_svector_ostream Out(buf);
2437 Out <<
"Assuming " << LhsString <<
" is ";
2439 if (!printValue(CondVarExpr, Out, N, TookTrue,
true))
2443 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2444 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2446 if (
const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
2447 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
2448 const ProgramState *
state = N->getState().get();
2449 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2450 if (report.isInteresting(R))
2451 event->setPrunable(
false);
2459 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTrueTest(
2461 BugReport &report,
const ExplodedNode *N,
bool TookTrue,
bool IsAssuming) {
2467 llvm::raw_svector_ostream Out(Buf);
2469 Out << (IsAssuming ?
"Assuming '" :
"'") << VD->getDeclName() <<
"' is ";
2471 if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
2475 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2479 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2481 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2482 const ProgramState *
state = N->getState().get();
2483 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2484 if (report.isInteresting(R))
2485 event->setPrunable(
false);
2487 SVal
V = state->getSVal(R);
2488 if (report.isInteresting(V))
2489 event->setPrunable(
false);
2492 return std::move(event);
2495 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTrueTest(
2497 BugReport &report,
const ExplodedNode *N,
bool TookTrue,
bool IsAssuming) {
2499 llvm::raw_svector_ostream Out(Buf);
2501 Out << (IsAssuming ?
"Assuming field '" :
"Field '")
2504 if (!printValue(ME, Out, N, TookTrue, IsAssuming))
2508 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2509 if (!Loc.isValid() || !Loc.asLocation().isValid())
2514 return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
2516 return std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2519 bool ConditionBRVisitor::printValue(
const Expr *CondVarExpr, raw_ostream &Out,
2520 const ExplodedNode *N,
bool TookTrue,
2525 Out << (TookTrue ?
"non-null" :
"null");
2530 Out << (TookTrue ?
"non-nil" :
"nil");
2541 if (IsAssuming || !IntValue.hasValue()) {
2543 Out << (TookTrue ?
"true" :
"false");
2545 Out << (TookTrue ?
"not equal to 0" :
"0");
2548 Out << (IntValue.getValue()->getBoolValue() ?
"true" :
"false");
2550 Out << *IntValue.getValue();
2556 const char *
const ConditionBRVisitor::GenericTrueMessage =
2557 "Assuming the condition is true";
2558 const char *
const ConditionBRVisitor::GenericFalseMessage =
2559 "Assuming the condition is false";
2561 bool ConditionBRVisitor::isPieceMessageGeneric(
2562 const PathDiagnosticPiece *Piece) {
2563 return Piece->getString() == GenericTrueMessage ||
2564 Piece->getString() == GenericFalseMessage;
2571 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
2572 BugReporterContext &BRC,
const ExplodedNode *N, BugReport &BR) {
2576 const Decl *D = N->getLocationContext()->getDecl();
2583 if (Options.ShouldSuppressFromCXXStandardLibrary) {
2584 BR.markInvalid(getTag(),
nullptr);
2593 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2595 if (CD->
getName() ==
"list") {
2596 BR.markInvalid(getTag(),
nullptr);
2603 if (
const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2605 if (CD->
getName() ==
"__independent_bits_engine") {
2606 BR.markInvalid(getTag(),
nullptr);
2624 if (CD->
getName() ==
"basic_string") {
2625 BR.markInvalid(getTag(),
nullptr);
2632 if (CD->
getName() ==
"shared_ptr") {
2633 BR.markInvalid(getTag(),
nullptr);
2646 if (SM.
getFilename(Loc).endswith(
"sys/queue.h")) {
2647 BR.markInvalid(getTag(),
nullptr);
2657 std::shared_ptr<PathDiagnosticPiece>
2658 UndefOrNullArgVisitor::VisitNode(
const ExplodedNode *N,
2659 BugReporterContext &BRC, BugReport &BR) {
2670 CallEventRef<> Call = CEMgr.
getCaller(CEnter->getCalleeContext(),
State);
2672 ArrayRef<ParmVarDecl *> parms = Call->parameters();
2674 for (
const auto ParamDecl : parms) {
2675 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2679 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2683 assert(ParamDecl &&
"Formal parameter has no decl?");
2698 SVal BoundVal = State->getSVal(R);
2699 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2700 BR.markInteresting(CEnter->getCalleeContext());
2711 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
2712 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
2714 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
2715 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
2717 VisitNode(EndPathNode, BRC, BR);
2720 llvm::SMTSolverRef RefutationSolver = llvm::CreateZ3Solver();
2724 for (
const auto &I : Constraints) {
2726 auto RangeIt = I.second.begin();
2729 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2731 while ((++RangeIt) != I.second.end()) {
2732 Constraints = RefutationSolver->mkOr(
2734 RangeIt->From(), RangeIt->To(),
2738 RefutationSolver->addConstraint(Constraints);
2743 if (!isSat.hasValue())
2746 if (!isSat.getValue())
2747 BR.markInvalid(
"Infeasible constraints", EndPathNode->getLocationContext());
2750 std::shared_ptr<PathDiagnosticPiece>
2751 FalsePositiveRefutationBRVisitor::VisitNode(
const ExplodedNode *N,
2752 BugReporterContext &,
2756 ConstraintRangeTy::Factory &
CF =
2757 N->getState()->get_context<ConstraintRange>();
2760 for (
auto const &C : NewCs) {
2762 if (!Constraints.contains(Sym)) {
2763 Constraints = CF.add(Constraints, Sym, C.second);
2770 void FalsePositiveRefutationBRVisitor::Profile(
2771 llvm::FoldingSetNodeID &
ID)
const {
2773 ID.AddPointer(&Tag);
2780 int NoteTag::Kind = 0;
2782 void TagVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
2784 ID.AddPointer(&Tag);
2787 std::shared_ptr<PathDiagnosticPiece>
2788 TagVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BRC,
2791 const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.
getTag());
2796 PathDiagnosticLocation Loc =
2798 auto Piece = std::make_shared<PathDiagnosticEventPiece>(Loc, *Msg);
2799 Piece->setPrunable(T->isPrunable());
ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC property.
Indicates that the tracked object is a CF object.
Defines the clang::ASTContext interface.
static ArrayRef< ParmVarDecl * > getCallParameters(CallEventRef<> Call)
Get parameters associated with runtime definition in order to get the correct parameter name...
This is a discriminated union of FileInfo and ExpansionInfo.
A (possibly-)qualified type.
static bool isPointerToConst(QualType Ty)
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static StringRef getMacroName(SourceLocation Loc, BugReporterContext &BRC)
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
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 CharSourceRange getTokenRange(SourceRange R)
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
static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)
Returns true if the given MacroID location points at the first token of the macro expansion...
Represents a variable declaration or definition.
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
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
static const Expr * peelOffPointerArithmetic(const BinaryOperator *B)
static CFGBlock * GetRelevantBlock(const ExplodedNode *Node)
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)
static Optional< const llvm::APSInt * > getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N)
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, const ExplodedNode *RightNode, SVal RightVal)
Comparing internal representations of symbolic values (via SVal::operator==()) is a valid way to chec...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
const Stmt * getCallSite() const
Represents a single basic block in a source-level CFG.
static bool potentiallyWritesIntoIvar(const Decl *Parent, const ObjCIvarDecl *Ivar)
Represents a point when we finish the call exit sequence (for inlined call).
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
This represents one expression.
Represents a character-granular source range.
CFGBlock * getBlock(Stmt *S)
Returns the CFGBlock the specified Stmt* appears in.
const Expr * getLastCondition() const
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.
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 std::shared_ptr< PathDiagnosticEventPiece > constructDebugPieceForTrackedCondition(const Expr *Cond, const ExplodedNode *N, BugReporterContext &BRC)
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
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 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
Stmt * getTerminatorStmt()
static void showBRParamDiagnostics(llvm::raw_svector_ostream &os, const VarRegion *VR, SVal V)
Display diagnostics for passing bad region as a parameter.
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
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).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
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.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
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
Skip past any parentheses which might surround this expression until reaching a fixed point...
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)