summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-03-30 19:27:42 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-03-30 19:27:42 +0000
commit95f9a68b1f8fa4d9a93b8eb5abc5c5c9bc58ee5b (patch)
tree8efbecd374834a29c231fab1f3209e5832ccf226 /clang/lib/StaticAnalyzer
parent6a5cd5e1cad601bfe3785654f6bbdfe81844bc07 (diff)
downloadbcm5719-llvm-95f9a68b1f8fa4d9a93b8eb5abc5c5c9bc58ee5b.tar.gz
bcm5719-llvm-95f9a68b1f8fa4d9a93b8eb5abc5c5c9bc58ee5b.zip
[analyzer] Track null or undef values through pointer arithmetic.
Pointer arithmetic on null or undefined pointers results in null or undefined pointers. This is obvious for undefined pointers; for null pointers it follows from our incorrect-but-somehow-working approach that declares that 0 (Loc) doesn't necessarily represent a pointer of numeric address value 0, but instead it represents any pointer that will cause a valid "null pointer dereference" issue when dereferenced. For now we've been seeing through pointer arithmetic at the original dereference expression, i.e. in bugreporter::getDerefExpr(), but not during further investigation of the value's origins in bugreporter::trackNullOrUndefValue(). The patch fixes it. Differential Revision: https://reviews.llvm.org/D45071 llvm-svn: 328896
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp26
1 files changed, 18 insertions, 8 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 0dd89271716..277ae28813d 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -75,6 +75,17 @@ bool bugreporter::isDeclRefExprToReference(const Expr *E) {
return false;
}
+static const Expr *peelOffPointerArithmetic(const BinaryOperator *B) {
+ if (B->isAdditiveOp() && B->getType()->isPointerType()) {
+ if (B->getLHS()->getType()->isPointerType()) {
+ return B->getLHS();
+ } else if (B->getRHS()->getType()->isPointerType()) {
+ return B->getRHS();
+ }
+ }
+ return nullptr;
+}
+
/// Given that expression S represents a pointer that would be dereferenced,
/// try to find a sub-expression from which the pointer came from.
/// This is used for tracking down origins of a null or undefined value:
@@ -101,14 +112,8 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
E = CE->getSubExpr();
} else if (const auto *B = dyn_cast<BinaryOperator>(E)) {
// Pointer arithmetic: '*(x + 2)' -> 'x') etc.
- if (B->getType()->isPointerType()) {
- if (B->getLHS()->getType()->isPointerType()) {
- E = B->getLHS();
- } else if (B->getRHS()->getType()->isPointerType()) {
- E = B->getRHS();
- } else {
- break;
- }
+ if (const Expr *Inner = peelOffPointerArithmetic(B)) {
+ E = Inner;
} else {
// Probably more arithmetic can be pattern-matched here,
// but for now give up.
@@ -1412,6 +1417,11 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
NI = NI->getFirstPred();
} while (NI);
}
+
+ if (auto *BO = dyn_cast<BinaryOperator>(Ex))
+ if (const Expr *SubEx = peelOffPointerArithmetic(BO))
+ return peelOffOuterExpr(SubEx, N);
+
return Ex;
}
OpenPOWER on IntegriCloud