diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 025c2898eee..f17f41a7ac9 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -228,6 +228,38 @@ static bool isFunctionMacroExpansion(SourceLocation Loc, return EInfo.isFunctionMacroExpansion(); } +/// \return Whether \c RegionOfInterest was modified at \p N, +/// where \p ReturnState is a state associated with the return +/// from the current frame. +static bool wasRegionOfInterestModifiedAt( + const SubRegion *RegionOfInterest, + const ExplodedNode *N, + SVal ValueAfter) { + ProgramStateRef State = N->getState(); + ProgramStateManager &Mgr = N->getState()->getStateManager(); + + if (!N->getLocationAs<PostStore>() + && !N->getLocationAs<PostInitializer>() + && !N->getLocationAs<PostStmt>()) + return false; + + // Writing into region of interest. + if (auto PS = N->getLocationAs<PostStmt>()) + if (auto *BO = PS->getStmtAs<BinaryOperator>()) + if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf( + N->getSVal(BO->getLHS()).getAsRegion())) + return true; + + // SVal after the state is possibly different. + SVal ValueAtN = N->getState()->getSVal(RegionOfInterest); + if (!Mgr.getSValBuilder().areEqual(State, ValueAtN, ValueAfter).isConstrainedTrue() && + (!ValueAtN.isUndef() || !ValueAfter.isUndef())) + return true; + + return false; +} + + namespace { /// Put a diagnostic on return statement of all inlined functions @@ -346,7 +378,7 @@ private: FramesModifyingCalculated.insert( N->getLocationContext()->getStackFrame()); - if (wasRegionOfInterestModifiedAt(N, LastReturnState, ValueAtReturn)) { + if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtReturn)) { const StackFrameContext *SCtx = N->getStackFrame(); while (!SCtx->inTopFrame()) { auto p = FramesModifyingRegion.insert(SCtx); @@ -365,33 +397,6 @@ private: } while (N); } - /// \return Whether \c RegionOfInterest was modified at \p N, - /// where \p ReturnState is a state associated with the return - /// from the current frame. - bool wasRegionOfInterestModifiedAt(const ExplodedNode *N, - ProgramStateRef ReturnState, - SVal ValueAtReturn) { - if (!N->getLocationAs<PostStore>() - && !N->getLocationAs<PostInitializer>() - && !N->getLocationAs<PostStmt>()) - return false; - - // Writing into region of interest. - if (auto PS = N->getLocationAs<PostStmt>()) - if (auto *BO = PS->getStmtAs<BinaryOperator>()) - if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf( - N->getSVal(BO->getLHS()).getAsRegion())) - return true; - - // SVal after the state is possibly different. - SVal ValueAtN = N->getState()->getSVal(RegionOfInterest); - if (!ReturnState->areEqual(ValueAtN, ValueAtReturn).isConstrainedTrue() && - (!ValueAtN.isUndef() || !ValueAtReturn.isUndef())) - return true; - - return false; - } - /// Get parameters associated with runtime definition in order /// to get the correct parameter name. ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) { @@ -524,25 +529,28 @@ private: } }; +/// Suppress null-pointer-dereference bugs where dereferenced null was returned +/// the macro. class MacroNullReturnSuppressionVisitor final : public BugReporterVisitor { const SubRegion *RegionOfInterest; + const SVal ValueAtDereference; -public: - MacroNullReturnSuppressionVisitor(const SubRegion *R) : RegionOfInterest(R) {} + // Do not invalidate the reports where the value was modified + // after it got assigned to from the macro. + bool WasModified = false; - static void *getTag() { - static int Tag = 0; - return static_cast<void *>(&Tag); - } - - void Profile(llvm::FoldingSetNodeID &ID) const override { - ID.AddPointer(getTag()); - } +public: + MacroNullReturnSuppressionVisitor(const SubRegion *R, + const SVal V) : RegionOfInterest(R), + ValueAtDereference(V) {} std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) override { + if (WasModified) + return nullptr; + auto BugPoint = BR.getErrorNode()->getLocation().getAs<StmtPoint>(); if (!BugPoint) return nullptr; @@ -556,6 +564,10 @@ public: BR.markInvalid(getTag(), MacroName.c_str()); } } + + if (wasRegionOfInterestModifiedAt(RegionOfInterest, N, ValueAtDereference)) + WasModified = true; + return nullptr; } @@ -568,7 +580,16 @@ public: if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths() && V.getAs<Loc>()) BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>( - R->getAs<SubRegion>())); + R->getAs<SubRegion>(), V)); + } + + void* getTag() const { + static int Tag = 0; + return static_cast<void *>(&Tag); + } + + void Profile(llvm::FoldingSetNodeID &ID) const override { + ID.AddPointer(getTag()); } private: |