summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp19
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp3
-rw-r--r--clang/test/Analysis/null-deref-offsets.c19
3 files changed, 23 insertions, 18 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index ec9fd6c75e0..d00182a871c 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -61,7 +61,9 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
return U->getSubExpr()->IgnoreParenCasts();
}
else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
+ if (ME->isImplicitAccess()) {
+ return ME;
+ } else if (ME->isArrow() || isDeclRefExprToReference(ME->getBase())) {
return ME->getBase()->IgnoreParenCasts();
} else {
// If we have a member expr with a dot, the base must have been
@@ -73,9 +75,9 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
return IvarRef->getBase()->IgnoreParenCasts();
}
else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) {
- return AE->getBase();
+ return getDerefExpr(AE->getBase());
}
- else if (isDeclRefExprToReference(E)) {
+ else if (isa<DeclRefExpr>(E)) {
return E;
}
break;
@@ -974,14 +976,11 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
// This code interacts heavily with this hack; otherwise the value
// would not be null at all for most fields, so we'd be unable to track it.
if (const auto *Op = dyn_cast<UnaryOperator>(Ex))
- if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue()) {
- Ex = Op->getSubExpr()->IgnoreParenCasts();
- while (const auto *ME = dyn_cast<MemberExpr>(Ex)) {
- Ex = ME->getBase()->IgnoreParenCasts();
- }
- }
+ if (Op->getOpcode() == UO_AddrOf && Op->getSubExpr()->isLValue())
+ if (const Expr *DerefEx = getDerefExpr(Op->getSubExpr()))
+ Ex = DerefEx;
- if (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex))
+ if (Ex && (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex)))
Inner = Ex;
}
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index dd7e9dd1178..3000e13d32c 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1338,6 +1338,9 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state,
/// the array). This is called by ExprEngine when evaluating casts
/// from arrays to pointers.
SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
+ if (Array.getAs<loc::ConcreteInt>())
+ return Array;
+
if (!Array.getAs<loc::MemRegionVal>())
return UnknownVal();
diff --git a/clang/test/Analysis/null-deref-offsets.c b/clang/test/Analysis/null-deref-offsets.c
index 567c47952b9..988cec4985d 100644
--- a/clang/test/Analysis/null-deref-offsets.c
+++ b/clang/test/Analysis/null-deref-offsets.c
@@ -7,7 +7,7 @@ struct S {
int z[2];
};
-void testOffsets(struct S *s) {
+void testOffsets(struct S *s, int coin) {
if (s != 0)
return;
@@ -21,14 +21,17 @@ void testOffsets(struct S *s) {
// FIXME: These should ideally be true.
clang_analyzer_eval(&(s->y) == 4); // expected-warning{{FALSE}}
- clang_analyzer_eval(&(s->z[0]) == 8); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(&(s->z[1]) == 12); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&(s->z[0]) == 8); // expected-warning{{FALSE}}
+ clang_analyzer_eval(&(s->z[1]) == 12); // expected-warning{{FALSE}}
// FIXME: These should ideally be false.
clang_analyzer_eval(&(s->y) == 0); // expected-warning{{TRUE}}
- clang_analyzer_eval(&(s->z[0]) == 0); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(&(s->z[1]) == 0); // expected-warning{{UNKNOWN}}
-
- // But this should still be a null dereference.
- s->y = 5; // expected-warning{{Access to field 'y' results in a dereference of a null pointer (loaded from variable 's')}}
+ clang_analyzer_eval(&(s->z[0]) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&(s->z[1]) == 0); // expected-warning{{TRUE}}
+
+ // But these should still be reported as null dereferences.
+ if (coin)
+ s->y = 5; // expected-warning{{Access to field 'y' results in a dereference of a null pointer (loaded from variable 's')}}
+ else
+ s->z[1] = 6; // expected-warning{{Array access (via field 'z') results in a null pointer dereference}}
}
OpenPOWER on IntegriCloud