summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-07-16 20:33:25 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-07-16 20:33:25 +0000
commitbccd6ec351dcd1223d59b4d4a48ac59c3817e521 (patch)
treefd1f6de441fda28309585e3540ac0722bbea03b9 /clang/lib
parent09885d05cebe699a61a09fd8f796b40d8de798b4 (diff)
downloadbcm5719-llvm-bccd6ec351dcd1223d59b4d4a48ac59c3817e521.tar.gz
bcm5719-llvm-bccd6ec351dcd1223d59b4d4a48ac59c3817e521.zip
[analyzer] Bugfix for an overly eager suppression for null pointer return from macros.
Only suppress those cases where the null which came from the macro is relevant to the bug, and was not overwritten in between. rdar://41497323 Differential Revision: https://reviews.llvm.org/D48856 llvm-svn: 337213
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp99
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:
OpenPOWER on IntegriCloud