diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-30 19:27:42 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-03-30 19:27:42 +0000 |
| commit | 95f9a68b1f8fa4d9a93b8eb5abc5c5c9bc58ee5b (patch) | |
| tree | 8efbecd374834a29c231fab1f3209e5832ccf226 /clang/lib/StaticAnalyzer | |
| parent | 6a5cd5e1cad601bfe3785654f6bbdfe81844bc07 (diff) | |
| download | bcm5719-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.cpp | 26 |
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; } |

