summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2017-12-12 02:27:55 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2017-12-12 02:27:55 +0000
commit3ef5deb3a790daa46f8947bab33563001445197c (patch)
treeba615c1ae71a6a2b6df14622ee817f29d9137670
parente8d85eaaa77e22142117e16a2c6922ca953ba4fe (diff)
downloadbcm5719-llvm-3ef5deb3a790daa46f8947bab33563001445197c.tar.gz
bcm5719-llvm-3ef5deb3a790daa46f8947bab33563001445197c.zip
[analyzer] In getSVal() API, disable auto-detection of void type as char type.
This is a follow-up from r314910. When a checker developer attempts to dereference a location in memory through ProgramState::getSVal(Loc) or ProgramState::getSVal(const MemRegion *), without specifying the second optional QualType parameter for the type of the value he tries to find at this location, the type is auto-detected from location type. If the location represents a value beyond a void pointer, we thought that auto-detecting the type as 'char' is a good idea. However, in most practical cases, the correct behavior would be to specify the type explicitly, as it is available from other sources, and the few cases where we actually need to take a 'char' are workarounds rather than an intended behavior. Therefore, try to fail with an easy-to-understand assertion when asked to read from a void pointer location. Differential Revision: https://reviews.llvm.org/D38801 llvm-svn: 320451
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h11
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp17
-rw-r--r--clang/lib/StaticAnalyzer/Core/RegionStore.cpp5
4 files changed, 23 insertions, 12 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index e3a2164b11f..dd2564b0a3c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -308,8 +308,12 @@ public:
/// \brief Return the value bound to the specified location.
/// Returns UnknownVal() if none found.
- SVal getSVal(const MemRegion* R) const;
+ SVal getSVal(const MemRegion* R, QualType T = QualType()) const;
+ /// \brief Return the value bound to the specified location, assuming
+ /// that the value is a scalar integer or an enumeration or a pointer.
+ /// Returns UnknownVal() if none found or the region is not known to hold
+ /// a value of such type.
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
/// \brief Visits the symbols reachable from the given SVal using the provided
@@ -758,9 +762,10 @@ inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const {
return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
}
-inline SVal ProgramState::getSVal(const MemRegion* R) const {
+inline SVal ProgramState::getSVal(const MemRegion* R, QualType T) const {
return getStateManager().StoreMgr->getBinding(getStore(),
- loc::MemRegionVal(R));
+ loc::MemRegionVal(R),
+ T);
}
inline BasicValueFactory &ProgramState::getBasicVals() const {
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 07285d27ed9..20a46843e23 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -179,7 +179,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(
if (const MemRegion *SValMemRegion = V.getAsRegion()) {
const ProgramStateRef State = C.getState();
- const SVal PSV = State->getSVal(SValMemRegion);
+ const SVal PSV = State->getSVal(SValMemRegion, C.getASTContext().CharTy);
if (PSV.isUndef()) {
if (ExplodedNode *N = C.generateErrorNode()) {
LazyInit_BT(BD, BT);
diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 883c6a66329..43966656cd8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -466,7 +466,7 @@ bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
}
Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
- const Expr* Arg) {
+ const Expr *Arg) {
ProgramStateRef State = C.getState();
SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
if (AddrVal.isUnknownOrUndef())
@@ -476,9 +476,18 @@ Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
if (!AddrLoc)
return None;
- const PointerType *ArgTy =
- dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
- return State->getSVal(*AddrLoc, ArgTy ? ArgTy->getPointeeType(): QualType());
+ QualType ArgTy = Arg->getType().getCanonicalType();
+ if (!ArgTy->isPointerType())
+ return None;
+
+ QualType ValTy = ArgTy->getPointeeType();
+
+ // Do not dereference void pointers. Treat them as byte pointers instead.
+ // FIXME: we might want to consider more than just the first byte.
+ if (ValTy->isVoidType())
+ ValTy = C.getASTContext().CharTy;
+
+ return State->getSVal(*AddrLoc, ValTy);
}
ProgramStateRef
diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index ecb32cc378d..7f2a481c6b0 100644
--- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1405,10 +1405,7 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
T = Ctx.VoidTy;
}
assert(!T.isNull() && "Unable to auto-detect binding type!");
- if (T->isVoidType()) {
- // When trying to dereference a void pointer, read the first byte.
- T = Ctx.CharTy;
- }
+ assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
}
OpenPOWER on IntegriCloud