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();
187 std::shared_ptr<PathDiagnosticPiece>
188 BugReporterVisitor::getEndPath(BugReporterContext &,
189 const ExplodedNode *, BugReport &) {
194 BugReporterVisitor::finalizeVisitor(BugReporterContext &,
195 const ExplodedNode *, BugReport &) {}
197 std::shared_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
198 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
199 PathDiagnosticLocation L =
202 const auto &Ranges = BR.getRanges();
206 auto P = std::make_shared<PathDiagnosticEventPiece>(
207 L, BR.getDescription(), Ranges.begin() == Ranges.end());
216 BugReporterContext &BRC) {
219 BRC.getSourceManager(),
220 BRC.getASTContext().getLangOpts());
241 const SubRegion *RegionOfInterest,
242 const ExplodedNode *N,
245 ProgramStateManager &Mgr = N->getState()->getStateManager();
253 if (
auto PS = N->getLocationAs<
PostStmt>())
255 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(
256 N->getSVal(BO->getLHS()).getAsRegion()))
260 SVal ValueAtN = N->getState()->getSVal(RegionOfInterest);
261 if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() &&
262 (!ValueAtN.isUndef() || !ValueAfter.isUndef()))
276 const SubRegion *RegionOfInterest;
277 MemRegionManager &MmrMgr;
284 static const unsigned DEREFERENCE_LIMIT = 2;
294 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingRegion;
295 llvm::SmallPtrSet<const StackFrameContext *, 32> FramesModifyingCalculated;
299 NoStoreFuncVisitor(
const SubRegion *R)
300 : RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
301 SM(MmrMgr.getContext().getSourceManager()),
302 PP(MmrMgr.getContext().getPrintingPolicy()) {}
304 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
307 ID.AddPointer(RegionOfInterest);
310 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
311 BugReporterContext &BR,
312 BugReport &)
override {
320 if (!CallExitLoc || isRegionOfInterestModifiedInFrame(N))
323 CallEventRef<> Call =
324 BR.getStateManager().getCallEventManager().getCaller(SCtx, State);
331 if (
const auto *MC = dyn_cast<ObjCMethodCall>(Call)) {
332 if (
const auto *IvarR = dyn_cast<ObjCIvarRegion>(RegionOfInterest)) {
333 const MemRegion *SelfRegion = MC->getReceiverSVal().getAsRegion();
334 if (RegionOfInterest->isSubRegionOf(SelfRegion) &&
335 potentiallyWritesIntoIvar(Call->getRuntimeDefinition().getDecl(),
337 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, SelfRegion,
343 if (
const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) {
344 const MemRegion *ThisR = CCall->getCXXThisVal().getAsRegion();
345 if (RegionOfInterest->isSubRegionOf(ThisR)
346 && !CCall->getDecl()->isImplicit())
347 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, ThisR,
357 for (
unsigned I = 0; I < Call->getNumArgs() && I < parameters.size(); ++I) {
359 SVal S = Call->getArgSVal(I);
363 int IndirectionLevel = 1;
365 while (
const MemRegion *R = S.getAsRegion()) {
367 return notModifiedDiagnostics(Ctx, *CallExitLoc, Call, {}, R,
368 ParamName, ParamIsReferenceType,
375 if (
auto P = findRegionOfInterestInRecord(RD, State, R))
376 return notModifiedDiagnostics(
377 Ctx, *CallExitLoc, Call, *
P, RegionOfInterest, ParamName,
378 ParamIsReferenceType, IndirectionLevel);
380 S = State->getSVal(R, PT);
399 const RegionVector &Vec = {},
402 if (depth == DEREFERENCE_LIMIT)
405 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
406 if (!RDX->hasDefinition())
411 if (
const auto *RDX = dyn_cast<CXXRecordDecl>(RD))
412 for (
const auto II : RDX->bases())
413 if (
const RecordDecl *RRD = II.getType()->getAsRecordDecl())
414 if (
auto Out = findRegionOfInterestInRecord(RRD, State, R, Vec, depth))
419 const FieldRegion *FR = MmrMgr.getFieldRegion(I, cast<SubRegion>(R));
420 const SVal V = State->getSVal(FR);
421 const MemRegion *VR = V.getAsRegion();
423 RegionVector VecF = Vec;
426 if (RegionOfInterest == VR)
431 findRegionOfInterestInRecord(RRD, State, FR, VecF, depth + 1))
439 findRegionOfInterestInRecord(RRD, State, VR, VecF, depth + 1))
449 bool potentiallyWritesIntoIvar(
const Decl *
Parent,
452 const char * IvarBind =
"Ivar";
453 if (!Parent || !Parent->
hasBody())
456 hasOperatorName(
"="),
457 hasLHS(ignoringParenImpCasts(
463 if (IvarRef->isFreeIvar())
466 const Expr *
Base = IvarRef->getBase();
467 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(Base))
468 Base = ICE->getSubExpr();
470 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Base))
471 if (
const auto *ID = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
483 bool isRegionOfInterestModifiedInFrame(
const ExplodedNode *N) {
486 if (!FramesModifyingCalculated.count(SCtx))
487 findModifyingFrames(N);
488 return FramesModifyingRegion.count(SCtx);
494 void findModifyingFrames(
const ExplodedNode *N) {
497 SVal ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
505 LastReturnState =
State;
506 ValueAtReturn = LastReturnState->getSVal(RegionOfInterest);
509 FramesModifyingCalculated.insert(
510 N->getLocationContext()->getStackFrame());
515 auto p = FramesModifyingRegion.insert(SCtx);
523 if (
auto CE = N->getLocationAs<
CallEnter>())
524 if (CE->getCalleeContext() == OriginalSCtx)
527 N = N->getFirstPred();
535 RuntimeDefinition RD = Call->getRuntimeDefinition();
536 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl()))
537 return FD->parameters();
538 if (
const auto *MD = dyn_cast_or_null<ObjCMethodDecl>(RD.getDecl()))
539 return MD->parameters();
541 return Call->parameters();
551 std::shared_ptr<PathDiagnosticPiece>
553 CallEventRef<> Call,
const RegionVector &FieldChain,
554 const MemRegion *MatchedRegion, StringRef FirstElement,
555 bool FirstIsReferenceType,
unsigned IndirectionLevel) {
557 PathDiagnosticLocation L;
561 L = PathDiagnosticLocation(
562 Call->getRuntimeDefinition().getDecl()->getSourceRange().getEnd(),
567 llvm::raw_svector_ostream os(sbuf);
568 os <<
"Returning without writing to '";
571 if (!prettyPrintRegionName(FirstElement, FirstIsReferenceType,
572 MatchedRegion, FieldChain, IndirectionLevel, os))
576 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
581 bool prettyPrintRegionName(StringRef FirstElement,
bool FirstIsReferenceType,
582 const MemRegion *MatchedRegion,
583 const RegionVector &FieldChain,
584 int IndirectionLevel,
585 llvm::raw_svector_ostream &os) {
587 if (FirstIsReferenceType)
590 RegionVector RegionSequence;
593 assert(RegionOfInterest->isSubRegionOf(MatchedRegion));
594 const MemRegion *R = RegionOfInterest;
595 while (R != MatchedRegion) {
596 RegionSequence.push_back(R);
597 R = cast<SubRegion>(R)->getSuperRegion();
599 std::reverse(RegionSequence.begin(), RegionSequence.end());
600 RegionSequence.append(FieldChain.begin(), FieldChain.end());
603 for (
const MemRegion *R : RegionSequence) {
607 if (isa<CXXBaseObjectRegion>(R) || isa<CXXTempObjectRegion>(R))
611 Sep = prettyPrintFirstElement(FirstElement,
613 IndirectionLevel, os);
618 if (!isa<DeclRegion>(R))
621 const auto *DR = cast<DeclRegion>(R);
622 Sep = DR->getValueType()->isAnyPointerType() ?
"->" :
".";
623 DR->getDecl()->getDeclName().print(os, PP);
627 prettyPrintFirstElement(FirstElement,
628 false, IndirectionLevel,
634 StringRef prettyPrintFirstElement(StringRef FirstElement,
635 bool MoreItemsExpected,
636 int IndirectionLevel,
637 llvm::raw_svector_ostream &os) {
640 if (IndirectionLevel > 0 && MoreItemsExpected) {
645 if (IndirectionLevel > 0 && MoreItemsExpected)
648 for (
int i=0; i<IndirectionLevel; i++)
652 if (IndirectionLevel > 0 && MoreItemsExpected)
662 const SubRegion *RegionOfInterest;
663 const SVal ValueAtDereference;
667 bool WasModified =
false;
670 MacroNullReturnSuppressionVisitor(
const SubRegion *R,
671 const SVal V) : RegionOfInterest(R),
672 ValueAtDereference(V) {}
674 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
675 BugReporterContext &BRC,
676 BugReport &BR)
override {
680 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
685 if (
auto Loc = matchAssignment(N)) {
690 BR.markInvalid(getTag(), MacroName.c_str());
700 static void addMacroVisitorIfNecessary(
701 const ExplodedNode *N,
const MemRegion *R,
702 bool EnableNullFPSuppression, BugReport &BR,
704 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
705 if (EnableNullFPSuppression &&
706 Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
707 BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
708 R->getAs<SubRegion>(), V));
711 void* getTag()
const {
713 return static_cast<void *
>(&Tag);
716 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
717 ID.AddPointer(getTag());
726 auto *LCtx = N->getLocationContext();
730 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
731 if (
const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
732 if (
const Expr *RHS = VD->getInit())
733 if (RegionOfInterest->isSubRegionOf(
734 State->getLValue(VD, LCtx).getAsRegion()))
735 return RHS->getBeginLoc();
736 }
else if (
const auto *BO = dyn_cast<BinaryOperator>(S)) {
737 const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
738 const Expr *RHS = BO->getRHS();
739 if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) {
762 bool EnableNullFPSuppression;
763 bool ShouldInvalidate =
true;
770 : StackFrame(Frame), EnableNullFPSuppression(Suppressed),
773 static void *getTag() {
775 return static_cast<void *
>(&Tag);
778 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
779 ID.AddPointer(ReturnVisitor::getTag());
780 ID.AddPointer(StackFrame);
781 ID.AddBoolean(EnableNullFPSuppression);
791 static void addVisitorIfNecessary(
const ExplodedNode *
Node,
const Stmt *S,
793 bool InEnableNullFPSuppression) {
800 if (CEE->getCalleeContext()->getCallSite() == S)
802 if (
auto SP = Node->getLocationAs<
StmtPoint>())
803 if (SP->getStmt() == S)
806 Node = Node->getFirstPred();
810 while (Node && Node->getLocation().getAs<
PostStmt>())
811 Node = Node->getFirstPred();
826 SVal RetVal = Node->getSVal(S);
829 if (cast<Expr>(S)->isGLValue())
831 RetVal = State->getSVal(*LValue);
836 bool EnableNullFPSuppression =
false;
837 if (InEnableNullFPSuppression &&
838 Options.ShouldSuppressNullReturnPaths)
840 EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
842 BR.markInteresting(CalleeContext);
843 BR.addVisitor(llvm::make_unique<ReturnVisitor>(CalleeContext,
844 EnableNullFPSuppression,
848 std::shared_ptr<PathDiagnosticPiece>
849 visitNodeInitial(
const ExplodedNode *N,
850 BugReporterContext &BRC, BugReport &BR) {
852 if (N->getLocationContext() != StackFrame)
859 const auto *Ret = dyn_cast<
ReturnStmt>(SP->getStmt());
866 SVal V = State->getSVal(Ret, StackFrame);
867 if (V.isUnknownOrUndef())
873 const Expr *RetE = Ret->getRetValue();
874 assert(RetE &&
"Tracking a return value for a void function");
879 if ((LValue = V.getAs<Loc>())) {
880 SVal RValue = State->getRawSVal(*LValue, RetE->
getType());
881 if (RValue.getAs<DefinedSVal>())
887 if (V.getAs<nonloc::LazyCompoundVal>() ||
888 V.getAs<nonloc::CompoundVal>())
894 bugreporter::trackExpressionValue(N, RetE, BR, EnableNullFPSuppression);
898 llvm::raw_svector_ostream Out(Msg);
900 if (State->isNull(V).isConstrainedTrue()) {
901 if (V.getAs<Loc>()) {
906 if (EnableNullFPSuppression &&
907 Options.ShouldAvoidSuppressingNullArgumentPaths)
908 Mode = MaybeUnsuppress;
911 Out <<
"Returning nil";
913 Out <<
"Returning null pointer";
916 Out <<
"Returning zero";
920 if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
921 Out <<
"Returning the value " << CI->getValue();
922 }
else if (V.getAs<Loc>()) {
923 Out <<
"Returning pointer";
925 Out <<
"Returning value";
930 if (
const MemRegion *MR = LValue->getAsRegion()) {
931 if (MR->canPrintPretty()) {
932 Out <<
" (reference to ";
933 MR->printPretty(Out);
939 if (
const auto *DR = dyn_cast<DeclRefExpr>(RetE))
940 if (
const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl()))
941 Out <<
" (loaded from '" << *DD <<
"')";
944 PathDiagnosticLocation L(Ret, BRC.getSourceManager(), StackFrame);
945 if (!L.isValid() || !L.asLocation().isValid())
948 return std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
951 std::shared_ptr<PathDiagnosticPiece>
952 visitNodeMaybeUnsuppress(
const ExplodedNode *N,
953 BugReporterContext &BRC, BugReport &BR) {
955 assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
963 if (CE->getCalleeContext() != StackFrame)
971 ProgramStateManager &StateMgr = BRC.getStateManager();
975 CallEventRef<> Call = CallMgr.
getCaller(StackFrame, State);
976 for (
unsigned I = 0, E = Call->getNumArgs(); I != E; ++I) {
981 const Expr *ArgE = Call->getArgExpr(I);
986 if (!State->isNull(*ArgV).isConstrainedTrue())
989 if (bugreporter::trackExpressionValue(N, ArgE, BR, EnableNullFPSuppression))
990 ShouldInvalidate =
false;
1000 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
1001 BugReporterContext &BRC,
1002 BugReport &BR)
override {
1005 return visitNodeInitial(N, BRC, BR);
1006 case MaybeUnsuppress:
1007 return visitNodeMaybeUnsuppress(N, BRC, BR);
1012 llvm_unreachable(
"Invalid visit mode!");
1015 void finalizeVisitor(BugReporterContext &,
const ExplodedNode *,
1016 BugReport &BR)
override {
1017 if (EnableNullFPSuppression && ShouldInvalidate)
1018 BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
1024 void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1026 ID.AddPointer(&tag);
1029 ID.AddBoolean(EnableNullFPSuppression);
1046 const MemSpaceRegion *VarSpace = VR->getMemorySpace();
1047 const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
1052 assert(VR->getDecl()->isStaticLocal() &&
"non-static stackless VarRegion");
1056 assert(VR->getDecl()->hasLocalStorage());
1063 const MemRegion *R, SVal V,
const DeclStmt *DS) {
1064 if (R->canPrintPretty()) {
1069 if (V.getAs<loc::ConcreteInt>()) {
1071 if (R->isBoundable()) {
1072 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1073 if (TR->getValueType()->isObjCObjectPointerType()) {
1074 os << action <<
"nil";
1080 os << action <<
"a null pointer value";
1082 }
else if (
auto CVal = V.getAs<nonloc::ConcreteInt>()) {
1083 os << action << CVal->getValue();
1086 if (isa<VarRegion>(R)) {
1088 if (VD->getInit()) {
1089 os << (R->canPrintPretty() ?
"initialized" :
"Initializing")
1090 <<
" to a garbage value";
1092 os << (R->canPrintPretty() ?
"declared" :
"Declaring")
1093 <<
" without an initial value";
1097 os << (R->canPrintPretty() ?
"initialized" :
"Initialized")
1105 const VarRegion *VR,
1107 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1111 if (V.getAs<loc::ConcreteInt>()) {
1112 if (Param->getType()->isObjCObjectPointerType())
1113 os <<
"nil object reference";
1115 os <<
"null pointer value";
1116 }
else if (V.isUndef()) {
1117 os <<
"uninitialized value";
1118 }
else if (
auto CI = V.getAs<nonloc::ConcreteInt>()) {
1119 os <<
"the value " << CI->getValue();
1125 unsigned Idx = Param->getFunctionScopeIndex() + 1;
1126 os <<
" via " << Idx << llvm::getOrdinalSuffix(Idx) <<
" parameter";
1127 if (VR->canPrintPretty()) {
1129 VR->printPretty(os);
1137 if (V.getAs<loc::ConcreteInt>()) {
1139 if (R->isBoundable()) {
1140 if (
const auto *TR = dyn_cast<TypedValueRegion>(R)) {
1141 if (TR->getValueType()->isObjCObjectPointerType()) {
1142 os <<
"nil object reference stored";
1148 if (R->canPrintPretty())
1149 os <<
"Null pointer value stored";
1151 os <<
"Storing null pointer value";
1154 }
else if (V.isUndef()) {
1155 if (R->canPrintPretty())
1156 os <<
"Uninitialized value stored";
1158 os <<
"Storing uninitialized value";
1160 }
else if (
auto CV = V.getAs<nonloc::ConcreteInt>()) {
1161 if (R->canPrintPretty())
1162 os <<
"The value " << CV->getValue() <<
" is assigned";
1164 os <<
"Assigning " << CV->getValue();
1167 if (R->canPrintPretty())
1168 os <<
"Value assigned";
1170 os <<
"Assigning value";
1173 if (R->canPrintPretty()) {
1179 std::shared_ptr<PathDiagnosticPiece>
1180 FindLastStoreBRVisitor::VisitNode(
const ExplodedNode *Succ,
1181 BugReporterContext &BRC, BugReport &BR) {
1185 const ExplodedNode *StoreSite =
nullptr;
1186 const ExplodedNode *Pred = Succ->getFirstPred();
1187 const Expr *InitE =
nullptr;
1188 bool IsParam =
false;
1191 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1194 InitE = VR->getDecl()->getInit();
1201 const MemRegion *FieldReg = (
const MemRegion *)PIP->getLocationValue();
1202 if (FieldReg && FieldReg == R) {
1204 InitE = PIP->getInitializer()->getInit();
1214 if (Succ->getState()->getSVal(R) != V)
1219 if (!PS || PS->getLocationValue() != R)
1229 if (BO->isAssignmentOp())
1230 InitE = BO->getRHS();
1237 if (
const auto *VR = dyn_cast<VarRegion>(R)) {
1239 const auto *Param = cast<ParmVarDecl>(VR->getDecl());
1241 ProgramStateManager &StateMgr = BRC.getStateManager();
1244 CallEventRef<> Call = CallMgr.
getCaller(CE->getCalleeContext(),
1246 InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
1253 if (
const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R))
1254 InitE = TmpR->getExpr();
1265 V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1268 bugreporter::trackExpressionValue(StoreSite, InitE, BR,
1269 EnableNullFPSuppression);
1272 BR, EnableNullFPSuppression);
1277 llvm::raw_svector_ostream os(sbuf);
1280 const Stmt *S = PS->getStmt();
1281 const char *action =
nullptr;
1282 const auto *DS = dyn_cast<
DeclStmt>(S);
1283 const auto *VR = dyn_cast<VarRegion>(R);
1286 action = R->canPrintPretty() ?
"initialized to " :
1288 }
else if (isa<BlockExpr>(S)) {
1289 action = R->canPrintPretty() ?
"captured by block as " :
1290 "Captured by block as ";
1294 SVal V = StoreSite->getSVal(S);
1295 if (
const auto *BDR =
1296 dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
1297 if (
const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
1298 if (
auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
1299 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1300 *KV, OriginalR, EnableNullFPSuppression));
1308 }
else if (StoreSite->getLocation().getAs<
CallEnter>()) {
1309 if (
const auto *VR = dyn_cast<VarRegion>(R))
1313 if (os.str().empty())
1318 PathDiagnosticLocation L;
1320 L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
1323 if (!L.isValid() || !L.asLocation().isValid())
1326 if (!L.isValid() || !L.asLocation().isValid())
1329 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1332 void TrackConstraintBRVisitor::Profile(llvm::FoldingSetNodeID &
ID)
const {
1334 ID.AddPointer(&tag);
1335 ID.AddBoolean(Assumption);
1341 const char *TrackConstraintBRVisitor::getTag() {
1342 return "TrackConstraintBRVisitor";
1345 bool TrackConstraintBRVisitor::isUnderconstrained(
const ExplodedNode *N)
const {
1347 return N->getState()->isNull(Constraint).isUnderconstrained();
1348 return (
bool)N->getState()->assume(Constraint, !Assumption);
1351 std::shared_ptr<PathDiagnosticPiece>
1352 TrackConstraintBRVisitor::VisitNode(
const ExplodedNode *N,
1353 BugReporterContext &BRC, BugReport &) {
1354 const ExplodedNode *PrevN = N->getFirstPred();
1360 if (!IsTrackingTurnedOn)
1361 if (!isUnderconstrained(N))
1362 IsTrackingTurnedOn =
true;
1363 if (!IsTrackingTurnedOn)
1368 if (isUnderconstrained(PrevN)) {
1374 assert(!isUnderconstrained(N));
1379 llvm::raw_svector_ostream os(sbuf);
1381 if (Constraint.getAs<Loc>()) {
1382 os <<
"Assuming pointer value is ";
1383 os << (Assumption ?
"non-null" :
"null");
1386 if (os.str().empty())
1391 PathDiagnosticLocation L =
1396 auto X = std::make_shared<PathDiagnosticEventPiece>(L, os.str());
1397 X->setTag(getTag());
1398 return std::move(
X);
1404 SuppressInlineDefensiveChecksVisitor::
1405 SuppressInlineDefensiveChecksVisitor(DefinedSVal
Value,
const ExplodedNode *N)
1408 AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
1409 if (!Options.ShouldSuppressInlinedDefensiveChecks)
1412 assert(N->getState()->isNull(V).isConstrainedTrue() &&
1413 "The visitor only tracks the cases where V is constrained to 0");
1416 void SuppressInlineDefensiveChecksVisitor::Profile(
1417 llvm::FoldingSetNodeID &
ID)
const {
1423 const char *SuppressInlineDefensiveChecksVisitor::getTag() {
1424 return "IDCVisitor";
1427 std::shared_ptr<PathDiagnosticPiece>
1428 SuppressInlineDefensiveChecksVisitor::VisitNode(
const ExplodedNode *Succ,
1429 BugReporterContext &BRC,
1431 const ExplodedNode *Pred = Succ->getFirstPred();
1436 if (!IsTrackingTurnedOn)
1437 if (Succ->getState()->isNull(V).isConstrainedTrue())
1438 IsTrackingTurnedOn =
true;
1439 if (!IsTrackingTurnedOn)
1444 if (!Pred->getState()->isNull(V).isConstrainedTrue()) {
1447 assert(Succ->getState()->isNull(V).isConstrainedTrue());
1451 const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
1452 if (CurLC != ReportLC && !CurLC->
isParentOf(ReportLC)) {
1453 BR.markInvalid(
"Suppress IDC", CurLC);
1461 auto BugPoint = BR.getErrorNode()->getLocation().getAs<
StmtPoint>();
1467 const Stmt *CurTerminatorStmt =
nullptr;
1469 CurTerminatorStmt = BE->getSrc()->getTerminator().getStmt();
1471 const Stmt *CurStmt = SP->getStmt();
1475 CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
1481 if (!CurTerminatorStmt)
1491 BR.markInvalid(
"Suppress Macro IDC", CurLC);
1500 const ExplodedNode *N) {
1501 if (
const auto *DR = dyn_cast<DeclRefExpr>(E)) {
1502 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1503 if (!VD->getType()->isReferenceType())
1505 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1506 MemRegionManager &MRMgr = StateMgr.getRegionManager();
1507 return MRMgr.getVarRegion(VD, N->getLocationContext());
1522 static const Expr *peelOffOuterExpr(
const Expr *Ex,
1523 const ExplodedNode *N) {
1525 if (
const auto *FE = dyn_cast<FullExpr>(Ex))
1526 return peelOffOuterExpr(FE->getSubExpr(), N);
1527 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
1528 return peelOffOuterExpr(OVE->getSourceExpr(), N);
1529 if (
const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
1531 if (PropRef && PropRef->isMessagingGetter()) {
1532 const Expr *GetterMessageSend =
1533 POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
1535 return peelOffOuterExpr(GetterMessageSend, N);
1540 if (
const auto *CO = dyn_cast<ConditionalOperator>(Ex)) {
1543 const ExplodedNode *NI = N;
1547 const CFGBlock *srcBlk = BE->getSrc();
1550 bool TookTrueBranch = (*(srcBlk->
succ_begin()) == BE->getDst());
1552 return peelOffOuterExpr(CO->getTrueExpr(), N);
1554 return peelOffOuterExpr(CO->getFalseExpr(), N);
1558 NI = NI->getFirstPred();
1562 if (
auto *BO = dyn_cast<BinaryOperator>(Ex))
1564 return peelOffOuterExpr(SubEx, N);
1566 if (
auto *UO = dyn_cast<UnaryOperator>(Ex)) {
1567 if (UO->getOpcode() == UO_LNot)
1568 return peelOffOuterExpr(UO->getSubExpr(), N);
1578 if (UO->getOpcode() == UO_AddrOf && UO->getSubExpr()->isLValue())
1579 if (
const Expr *DerefEx = bugreporter::getDerefExpr(UO->getSubExpr()))
1580 return peelOffOuterExpr(DerefEx, N);
1588 static const ExplodedNode* findNodeForExpression(
const ExplodedNode *N,
1589 const Expr *Inner) {
1593 N = N->getFirstPred();
1598 bool bugreporter::trackExpressionValue(
const ExplodedNode *InputNode,
1599 const Expr *E, BugReport &report,
1600 bool EnableNullFPSuppression) {
1601 if (!E || !InputNode)
1604 const Expr *Inner = peelOffOuterExpr(E, InputNode);
1605 const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
1614 if (
const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
1615 trackExpressionValue(LVNode, Receiver, report, EnableNullFPSuppression);
1620 SVal LVal = LVNode->getSVal(Inner);
1623 bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
1628 if (RR && !LVIsNull)
1629 if (
auto KV = LVal.getAs<KnownSVal>())
1630 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1631 *KV, RR, EnableNullFPSuppression));
1637 const MemRegion *R = (RR && LVIsNull) ? RR :
1638 LVNode->getSVal(Inner).getAsRegion();
1643 SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
1645 llvm::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R)));
1647 MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
1648 LVNode, R, EnableNullFPSuppression, report, V);
1650 report.markInteresting(V);
1651 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(R));
1654 if (V.getAsLocSymbol(
true))
1655 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1656 V.castAs<DefinedSVal>(),
false));
1659 if (
auto DV = V.getAs<DefinedSVal>())
1660 if (!DV->isZeroConstant() && LVState->isNull(*DV).isConstrainedTrue() &&
1661 EnableNullFPSuppression)
1663 llvm::make_unique<SuppressInlineDefensiveChecksVisitor>(*DV,
1666 if (
auto KV = V.getAs<KnownSVal>())
1667 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1668 *KV, R, EnableNullFPSuppression));
1675 SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
1677 ReturnVisitor::addVisitorIfNecessary(
1678 LVNode, Inner, report, EnableNullFPSuppression);
1681 if (
auto L = V.getAs<loc::MemRegionVal>()) {
1682 report.addVisitor(llvm::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
1688 bool CanDereference =
true;
1689 if (
const auto *SR = dyn_cast<SymbolicRegion>(L->getRegion()))
1690 if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
1691 CanDereference =
false;
1698 RVal = LVState->getRawSVal(L.getValue(), Inner->
getType());
1699 }
else if (CanDereference) {
1700 RVal = LVState->getSVal(L->getRegion());
1704 if (
auto KV = RVal.getAs<KnownSVal>())
1705 report.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1706 *KV, L->getRegion(), EnableNullFPSuppression));
1708 const MemRegion *RegionRVal = RVal.getAsRegion();
1709 if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
1710 report.markInteresting(RegionRVal);
1711 report.addVisitor(llvm::make_unique<TrackConstraintBRVisitor>(
1712 loc::MemRegionVal(RegionRVal),
false));
1718 const Expr *NilReceiverBRVisitor::getNilReceiver(
const Stmt *S,
1719 const ExplodedNode *N) {
1723 if (
const Expr *Receiver = ME->getInstanceReceiver()) {
1725 SVal V = N->getSVal(Receiver);
1726 if (state->isNull(V).isConstrainedTrue())
1732 std::shared_ptr<PathDiagnosticPiece>
1733 NilReceiverBRVisitor::VisitNode(
const ExplodedNode *N,
1734 BugReporterContext &BRC, BugReport &BR) {
1739 const Stmt *S = P->getStmt();
1740 const Expr *Receiver = getNilReceiver(S, N);
1745 llvm::raw_svector_ostream
OS(Buf);
1747 if (
const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
1749 ME->getSelector().print(OS);
1750 OS <<
"' not called";
1753 OS <<
"No method is called";
1755 OS <<
" because the receiver is nil";
1760 bugreporter::trackExpressionValue(N, Receiver, BR,
1763 PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
1764 N->getLocationContext());
1765 return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
1769 void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
1771 bool EnableNullFPSuppression) {
1772 const ExplodedNode *N = BR.getErrorNode();
1773 std::deque<const Stmt *> WorkList;
1774 WorkList.push_back(S);
1776 while (!WorkList.empty()) {
1777 const Stmt *Head = WorkList.front();
1778 WorkList.pop_front();
1780 ProgramStateManager &StateMgr = N->getState()->getStateManager();
1782 if (
const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
1783 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
1784 const VarRegion *R =
1785 StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
1788 SVal V = N->getSVal(S);
1790 if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
1792 BR.addVisitor(llvm::make_unique<FindLastStoreBRVisitor>(
1793 V.castAs<KnownSVal>(), R, EnableNullFPSuppression));
1799 WorkList.push_back(SubStmt);
1809 const char *ConditionBRVisitor::getTag() {
1810 return "ConditionBRVisitor";
1813 std::shared_ptr<PathDiagnosticPiece>
1814 ConditionBRVisitor::VisitNode(
const ExplodedNode *N,
1815 BugReporterContext &BRC, BugReport &BR) {
1816 auto piece = VisitNodeImpl(N, BRC, BR);
1818 piece->setTag(getTag());
1819 if (
auto *ev = dyn_cast<PathDiagnosticEventPiece>(piece.get()))
1820 ev->setPrunable(
true,
false);
1825 std::shared_ptr<PathDiagnosticPiece>
1826 ConditionBRVisitor::VisitNodeImpl(
const ExplodedNode *N,
1827 BugReporterContext &BRC, BugReport &BR) {
1835 if (CurrentState->getGDM().getRoot() ==
1836 PrevState->getGDM().getRoot())
1842 const CFGBlock *srcBlk = BE->getSrc();
1844 return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC);
1849 const std::pair<const ProgramPointTag *, const ProgramPointTag *> &tags =
1853 if (tag == tags.first)
1854 return VisitTrueTest(cast<Expr>(PS->getStmt()),
true,
1856 if (tag == tags.second)
1857 return VisitTrueTest(cast<Expr>(PS->getStmt()),
false,
1866 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTerminator(
1867 const Stmt *Term,
const ExplodedNode *N,
const CFGBlock *srcBlk,
1868 const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
1869 const Expr *Cond =
nullptr;
1889 case Stmt::IfStmtClass:
1890 Cond = cast<IfStmt>(Term)->getCond();
1892 case Stmt::ConditionalOperatorClass:
1893 Cond = cast<ConditionalOperator>(Term)->getCond();
1895 case Stmt::BinaryOperatorClass:
1899 const auto *BO = cast<BinaryOperator>(Term);
1900 assert(BO->isLogicalOp() &&
1901 "CFG terminator is not a short-circuit operator!");
1902 Cond = BO->getLHS();
1909 while (
const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
1910 if (!InnerBO->isLogicalOp())
1917 const bool tookTrue = *(srcBlk->
succ_begin()) == dstBlk;
1918 return VisitTrueTest(Cond, tookTrue, BRC, R, N);
1921 std::shared_ptr<PathDiagnosticPiece>
1922 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond,
bool tookTrue,
1923 BugReporterContext &BRC, BugReport &R,
1924 const ExplodedNode *N) {
1927 const Expr *CondTmp = Cond;
1928 bool tookTrueTmp = tookTrue;
1935 case Stmt::BinaryOperatorClass:
1936 if (
auto P = VisitTrueTest(Cond, cast<BinaryOperator>(CondTmp),
1937 tookTrueTmp, BRC, R, N))
1940 case Stmt::DeclRefExprClass:
1941 if (
auto P = VisitTrueTest(Cond, cast<DeclRefExpr>(CondTmp),
1942 tookTrueTmp, BRC, R, N))
1945 case Stmt::UnaryOperatorClass: {
1946 const auto *UO = cast<UnaryOperator>(CondTmp);
1947 if (UO->getOpcode() == UO_LNot) {
1948 tookTrueTmp = !tookTrueTmp;
1949 CondTmp = UO->getSubExpr();
1961 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
1962 if (!Loc.isValid() || !Loc.asLocation().isValid())
1965 return std::make_shared<PathDiagnosticEventPiece>(
1966 Loc, tookTrue ? GenericTrueMessage : GenericFalseMessage);
1969 bool ConditionBRVisitor::patternMatch(
const Expr *Ex,
1970 const Expr *ParentEx,
1972 BugReporterContext &BRC,
1974 const ExplodedNode *N,
1976 const Expr *OriginalExpr = Ex;
1984 (isa<GNUNullExpr>(Ex) ||
1985 isa<ObjCBoolLiteralExpr>(Ex) ||
1986 isa<CXXBoolLiteralExpr>(Ex) ||
1987 isa<IntegerLiteral>(Ex) ||
1988 isa<FloatingLiteral>(Ex))) {
1990 BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1992 BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
1993 bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
1995 bool partOfParentMacro =
false;
1999 BRC.getASTContext().getLangOpts());
2000 partOfParentMacro = PName.equals(StartName);
2003 if (beginAndEndAreTheSameMacro && !partOfParentMacro ) {
2008 LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart);
2011 Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
2019 if (
const auto *DR = dyn_cast<DeclRefExpr>(Ex)) {
2020 const bool quotes = isa<VarDecl>(DR->getDecl());
2024 const ProgramState *
state = N->getState().get();
2025 if (
const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
2026 LCtx).getAsRegion()) {
2027 if (report.isInteresting(R))
2030 const ProgramState *state = N->getState().get();
2031 SVal V = state->getSVal(R);
2032 if (report.isInteresting(V))
2037 Out << DR->getDecl()->getDeclName().getAsString();
2043 if (
const auto *IL = dyn_cast<IntegerLiteral>(Ex)) {
2046 if (IL->getValue() == 0) {
2052 if (IL->getValue() == 0) {
2058 Out << IL->getValue();
2065 std::shared_ptr<PathDiagnosticPiece>
2067 const bool tookTrue, BugReporterContext &BRC,
2068 BugReport &R,
const ExplodedNode *N) {
2069 bool shouldInvert =
false;
2074 llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
2075 const bool isVarLHS = patternMatch(BExpr->
getLHS(), BExpr, OutLHS,
2076 BRC, R, N, shouldPrune);
2077 const bool isVarRHS = patternMatch(BExpr->
getRHS(), BExpr, OutRHS,
2078 BRC, R, N, shouldPrune);
2080 shouldInvert = !isVarLHS && isVarRHS;
2088 return VisitConditionVariable(LhsString, BExpr->
getLHS(), tookTrue,
2094 if (LhsString.empty() || RhsString.empty() ||
2100 llvm::raw_svector_ostream Out(buf);
2101 Out <<
"Assuming " << (shouldInvert ? RhsString : LhsString) <<
" is ";
2107 case BO_LT: Op = BO_GT;
break;
2108 case BO_GT: Op = BO_LT;
break;
2109 case BO_LE: Op = BO_GE;
break;
2110 case BO_GE: Op = BO_LE;
break;
2115 case BO_EQ: Op = BO_NE;
break;
2116 case BO_NE: Op = BO_EQ;
break;
2117 case BO_LT: Op = BO_GE;
break;
2118 case BO_GT: Op = BO_LE;
break;
2119 case BO_LE: Op = BO_GT;
break;
2120 case BO_GE: Op = BO_LT;
break;
2130 Out <<
"not equal to ";
2137 Out << (shouldInvert ? LhsString : RhsString);
2139 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2140 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2141 if (shouldPrune.hasValue())
2142 event->setPrunable(shouldPrune.getValue());
2146 std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable(
2147 StringRef LhsString,
const Expr *CondVarExpr,
const bool tookTrue,
2148 BugReporterContext &BRC, BugReport &report,
const ExplodedNode *N) {
2153 llvm::raw_svector_ostream Out(buf);
2154 Out <<
"Assuming " << LhsString <<
" is ";
2159 Out << (tookTrue ?
"not null" :
"null");
2161 Out << (tookTrue ?
"not nil" :
"nil");
2163 Out << (tookTrue ?
"true" :
"false");
2165 Out << (tookTrue ?
"non-zero" :
"zero");
2170 PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
2171 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2173 if (
const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
2174 if (
const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
2175 const ProgramState *
state = N->getState().get();
2176 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2177 if (report.isInteresting(R))
2178 event->setPrunable(
false);
2186 std::shared_ptr<PathDiagnosticPiece>
2187 ConditionBRVisitor::VisitTrueTest(
const Expr *Cond,
const DeclRefExpr *DR,
2188 const bool tookTrue, BugReporterContext &BRC,
2189 BugReport &report,
const ExplodedNode *N) {
2195 llvm::raw_svector_ostream Out(Buf);
2197 Out <<
"Assuming '" << VD->getDeclName() <<
"' is ";
2202 Out << (tookTrue ?
"non-null" :
"null");
2204 Out << (tookTrue ?
"non-nil" :
"nil");
2206 Out << (tookTrue ?
"not equal to 0" :
"0");
2211 PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
2212 auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
2214 const ProgramState *
state = N->getState().get();
2215 if (
const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
2216 if (report.isInteresting(R))
2217 event->setPrunable(
false);
2219 SVal V = state->getSVal(R);
2220 if (report.isInteresting(V))
2221 event->setPrunable(
false);
2224 return std::move(event);
2227 const char *
const ConditionBRVisitor::GenericTrueMessage =
2228 "Assuming the condition is true";
2229 const char *
const ConditionBRVisitor::GenericFalseMessage =
2230 "Assuming the condition is false";
2232 bool ConditionBRVisitor::isPieceMessageGeneric(
2233 const PathDiagnosticPiece *Piece) {
2234 return Piece->getString() == GenericTrueMessage ||
2235 Piece->getString() == GenericFalseMessage;
2238 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
2239 BugReporterContext &BRC,
const ExplodedNode *N, BugReport &BR) {
2243 const Decl *D = N->getLocationContext()->getDecl();
2250 if (Options.ShouldSuppressFromCXXStandardLibrary) {
2251 BR.markInvalid(getTag(),
nullptr);
2260 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
2262 if (CD->
getName() ==
"list") {
2263 BR.markInvalid(getTag(),
nullptr);
2270 if (
const auto *MD = dyn_cast<CXXConstructorDecl>(D)) {
2272 if (CD->
getName() ==
"__independent_bits_engine") {
2273 BR.markInvalid(getTag(),
nullptr);
2291 if (CD->
getName() ==
"basic_string") {
2292 BR.markInvalid(getTag(),
nullptr);
2299 if (CD->
getName() ==
"shared_ptr") {
2300 BR.markInvalid(getTag(),
nullptr);
2313 if (SM.
getFilename(Loc).endswith(
"sys/queue.h")) {
2314 BR.markInvalid(getTag(),
nullptr);
2320 std::shared_ptr<PathDiagnosticPiece>
2321 UndefOrNullArgVisitor::VisitNode(
const ExplodedNode *N,
2322 BugReporterContext &BRC, BugReport &BR) {
2333 CallEventRef<> Call = CEMgr.
getCaller(CEnter->getCalleeContext(),
State);
2337 for (
const auto ParamDecl : parms) {
2338 const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion();
2342 if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts()))
2346 assert(ParamDecl &&
"Formal parameter has no decl?");
2361 SVal BoundVal = State->getSVal(R);
2362 if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
2363 BR.markInteresting(CEnter->getCalleeContext());
2370 std::shared_ptr<PathDiagnosticPiece>
2371 CXXSelfAssignmentBRVisitor::VisitNode(
const ExplodedNode *Succ,
2372 BugReporterContext &BRC, BugReport &) {
2377 if (!Edge.hasValue())
2380 auto Tag = Edge->
getTag();
2384 if (Tag->getTagDescription() !=
"cplusplus.SelfAssignment")
2390 dyn_cast<
CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());
2391 assert(Met &&
"Not a C++ method.");
2392 assert((Met->isCopyAssignmentOperator() || Met->isMoveAssignmentOperator()) &&
2393 "Not a copy/move assignment operator.");
2395 const auto *LCtx = Edge->getLocationContext();
2397 const auto &
State = Succ->getState();
2398 auto &SVB =
State->getStateManager().getSValBuilder();
2401 State->getSVal(
State->getRegion(Met->getParamDecl(0), LCtx));
2403 State->getSVal(SVB.getCXXThis(Met, LCtx->getStackFrame()));
2407 if (!L.isValid() || !L.asLocation().isValid())
2411 llvm::raw_svector_ostream Out(Buf);
2413 Out <<
"Assuming " << Met->getParamDecl(0)->getName() <<
2414 ((Param == This) ?
" == " :
" != ") <<
"*this";
2416 auto Piece = std::make_shared<PathDiagnosticEventPiece>(L, Out.str());
2417 Piece->addRange(Met->getSourceRange());
2419 return std::move(Piece);
2422 std::shared_ptr<PathDiagnosticPiece>
2423 TaintBugVisitor::VisitNode(
const ExplodedNode *N,
2424 BugReporterContext &BRC, BugReport &) {
2427 if (!N->getState()->isTainted(V) || N->getFirstPred()->getState()->isTainted(V))
2435 PathDiagnosticLocation L =
2437 if (!L.isValid() || !L.asLocation().isValid())
2440 return std::make_shared<PathDiagnosticEventPiece>(L,
"Taint originated here");
2443 FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
2444 : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
2446 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
2447 BugReporterContext &BRC,
const ExplodedNode *EndPathNode, BugReport &BR) {
2449 VisitNode(EndPathNode, BRC, BR);
2456 for (
const auto &I : Constraints) {
2458 auto RangeIt = I.second.begin();
2461 RefutationSolver, Ctx, Sym, RangeIt->From(), RangeIt->To(),
2463 while ((++RangeIt) != I.second.end()) {
2464 Constraints = RefutationSolver->mkOr(
2466 RangeIt->From(), RangeIt->To(),
2470 RefutationSolver->addConstraint(Constraints);
2475 if (!isSat.hasValue())
2478 if (!isSat.getValue())
2479 BR.markInvalid(
"Infeasible constraints", EndPathNode->getLocationContext());
2482 std::shared_ptr<PathDiagnosticPiece>
2483 FalsePositiveRefutationBRVisitor::VisitNode(
const ExplodedNode *N,
2484 BugReporterContext &,
2488 ConstraintRangeTy::Factory &
CF =
2489 N->getState()->get_context<ConstraintRange>();
2492 for (
auto const &C : NewCs) {
2494 if (!Constraints.contains(Sym)) {
2495 Constraints = CF.add(Constraints, Sym, C.second);
2502 void FalsePositiveRefutationBRVisitor::Profile(
2503 llvm::FoldingSetNodeID &
ID)
const {
2505 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.
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...
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.