aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-08-04 00:25:30 +0000
committerJordan Rose <jordan_rose@apple.com>2012-08-04 00:25:30 +0000
commit522f46f497d9ccecc8bc2f5ec132b9bb7060dee1 (patch)
tree42ef5544bc0d67d1eaf361bbb5c950af31c17953 /lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
parentaa6eccce0cd6e15229cdee52177477371890d3c4 (diff)
[analyzer] Don't assume values bound to references are automatically non-null.
While there is no such thing as a "null reference" in the C++ standard, many implementations of references (including Clang's) do not actually check that the location bound to them is non-null. Thus unlike a regular null dereference, this will not cause a problem at runtime until the reference is actually used. In order to catch these cases, we need to not prune out paths on which the input pointer is null. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161288 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index a94d7a773e..e98c131ce9 100644
--- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -233,7 +233,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
CheckerContext &C) const {
- // If we're binding to a reference, check if the value is potentially null.
+ // If we're binding to a reference, check if the value is known to be null.
if (V.isUndef())
return;
@@ -265,8 +265,23 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
}
}
- // From here on out, assume the value is non-null.
- C.addTransition(StNonNull);
+ // Unlike a regular null dereference, initializing a reference with a
+ // dereferenced null pointer does not actually cause a runtime exception in
+ // Clang's implementation of references.
+ //
+ // int &r = *p; // safe??
+ // if (p != NULL) return; // uh-oh
+ // r = 5; // trap here
+ //
+ // The standard says this is invalid as soon as we try to create a "null
+ // reference" (there is no such thing), but turning this into an assumption
+ // that 'p' is never null will not match our actual runtime behavior.
+ // So we do not record this assumption, allowing us to warn on the last line
+ // of this example.
+ //
+ // We do need to add a transition because we may have generated a sink for
+ // the "implicit" null dereference.
+ C.addTransition(State, this);
}
void ento::registerDereferenceChecker(CheckerManager &mgr) {