diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
| -rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 27 | ||||
| -rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 4 | ||||
| -rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 3 | ||||
| -rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 12 |
4 files changed, 37 insertions, 9 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 7309741d22e3..d00182a871c1 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/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; @@ -961,7 +963,24 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Expr *Inner = nullptr; if (const Expr *Ex = dyn_cast<Expr>(S)) { Ex = Ex->IgnoreParenCasts(); - if (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex)) + + // Performing operator `&' on an lvalue expression is essentially a no-op. + // Then, if we are taking addresses of fields or elements, these are also + // unlikely to matter. + // FIXME: There's a hack in our Store implementation that always computes + // field offsets around null pointers as if they are always equal to 0. + // The idea here is to report accesses to fields as null dereferences + // even though the pointer value that's being dereferenced is actually + // the offset of the field rather than exactly 0. + // See the FIXME in StoreManager's getLValueFieldOrIvar() method. + // 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()) + if (const Expr *DerefEx = getDerefExpr(Op->getSubExpr())) + Ex = DerefEx; + + if (Ex && (ExplodedGraph::isInterestingLValueExpr(Ex) || CallEvent::isCallStmt(Ex))) Inner = Ex; } diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 9e6ec09010e9..8ee34190891a 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1904,8 +1904,8 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { // Evaluate the LHS of the case value. llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext()); - assert(V1.getBitWidth() == getContext().getTypeSize(CondE->getType())); - + assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType())); + // Get the RHS of the case, if it exists. llvm::APSInt V2; if (const Expr *E = Case->getRHS()) diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index dd7e9dd11781..3000e13d32c6 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/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/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index ba48a60d5a1c..1af49f68cc05 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -404,9 +404,15 @@ SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { case loc::ConcreteIntKind: // While these seem funny, this can happen through casts. - // FIXME: What we should return is the field offset. For example, - // add the field offset to the integer value. That way funny things + // FIXME: What we should return is the field offset, not base. For example, + // add the field offset to the integer value. That way things // like this work properly: &(((struct foo *) 0xa)->f) + // However, that's not easy to fix without reducing our abilities + // to catch null pointer dereference. Eg., ((struct foo *)0x0)->f = 7 + // is a null dereference even though we're dereferencing offset of f + // rather than null. Coming up with an approach that computes offsets + // over null pointers properly while still being able to catch null + // dereferences might be worth it. return Base; default: @@ -431,7 +437,7 @@ SVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, // If the base is an unknown or undefined value, just return it back. // FIXME: For absolute pointer addresses, we just return that value back as // well, although in reality we should return the offset added to that - // value. + // value. See also the similar FIXME in getLValueFieldOrIvar(). if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>()) return Base; |
