[analyzer] DynamicSize: Remove 'getSizeInElements()' from store

Summary:
This patch uses the new `DynamicSize.cpp` to serve dynamic information.
Previously it was static and probably imprecise data.

Reviewed By: NoQ

Differential Revision: https://reviews.llvm.org/D69599
This commit is contained in:
Charusso 2020-01-30 16:51:26 +01:00
parent 4801522432
commit af3d0d1628
8 changed files with 45 additions and 66 deletions

View File

@ -26,6 +26,12 @@ namespace ento {
DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
SValBuilder &SVB);
/// Get the stored element count of the region \p MR.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
QualType ElementTy);
} // namespace ento
} // namespace clang

View File

@ -148,14 +148,6 @@ public:
virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
// FIXME: This should soon be eliminated altogether; clients should deal with
// region extents directly.
virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
const MemRegion *region,
QualType EleTy) {
return UnknownVal();
}
/// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;

View File

@ -16,6 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@ -54,12 +55,11 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
ProgramStateRef state = C.getState();
// Get the size of the array.
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType());
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateErrorNode(StOutBound);
if (!N)

View File

@ -16,6 +16,7 @@
#include "MPIChecker.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
namespace clang {
namespace ento {
@ -160,10 +161,11 @@ void MPIChecker::allRegionsUsedByWait(
return;
}
const auto &Size = Ctx.getStoreManager().getSizeInElements(
Ctx.getState(), SuperRegion,
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
Ctx.getState(), SuperRegion, Ctx.getSValBuilder(),
CE.getArgExpr(1)->getType()->getPointeeType());
const llvm::APSInt &ArrSize = Size.getAs<nonloc::ConcreteInt>()->getValue();
const llvm::APSInt &ArrSize =
ElementCount.getAs<nonloc::ConcreteInt>()->getValue();
for (size_t i = 0; i < ArrSize; ++i) {
const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);

View File

@ -16,6 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@ -51,15 +52,14 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
// pointer casts.
if (Idx.isZeroConstant())
return;
// FIXME: All of this out-of-bounds checking should eventually be refactored
// into a common place.
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateErrorNode(StOutBound);

View File

@ -16,6 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@ -50,10 +51,10 @@ static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) {
return false;
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal NumElements = C.getStoreManager().getSizeInElements(
state, ER->getSuperRegion(), ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
state, ER->getSuperRegion(), C.getSValBuilder(), ER->getValueType());
ProgramStateRef StInBound = state->assumeInBound(Idx, ElementCount, true);
ProgramStateRef StOutBound = state->assumeInBound(Idx, ElementCount, false);
return StOutBound && !StInBound;
}

View File

@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
@ -26,5 +27,22 @@ DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
return MR->getMemRegionManager().getStaticSize(MR, SVB);
}
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
const MemRegion *MR,
SValBuilder &SVB,
QualType ElementTy) {
MemRegionManager &MemMgr = MR->getMemRegionManager();
ASTContext &Ctx = MemMgr.getContext();
DefinedOrUnknownSVal Size = getDynamicSize(State, MR, SVB);
SVal ElementSizeV = SVB.makeIntVal(
Ctx.getTypeSizeInChars(ElementTy).getQuantity(), SVB.getArrayIndexType());
SVal DivisionV =
SVB.evalBinOp(State, BO_Div, Size, ElementSizeV, SVB.getArrayIndexType());
return DivisionV.castAs<DefinedOrUnknownSVal>();
}
} // namespace ento
} // namespace clang

View File

@ -622,15 +622,6 @@ public: // Part of public interface to class.
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper) override;
//===------------------------------------------------------------------===//
// Region "extents".
//===------------------------------------------------------------------===//
// FIXME: This method will soon be eliminated; see the note in Store.h.
DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
const MemRegion* R,
QualType EleTy) override;
//===------------------------------------------------------------------===//
// Utility methods.
//===------------------------------------------------------------------===//
@ -1387,37 +1378,6 @@ RegionStoreManager::invalidateRegions(Store store,
return StoreRef(B.asStore(), *this);
}
//===----------------------------------------------------------------------===//
// Extents for regions.
//===----------------------------------------------------------------------===//
DefinedOrUnknownSVal
RegionStoreManager::getSizeInElements(ProgramStateRef state,
const MemRegion *R,
QualType EleTy) {
DefinedOrUnknownSVal Size = getDynamicSize(state, R, svalBuilder);
const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
if (!SizeInt)
return UnknownVal();
CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
if (Ctx.getAsVariableArrayType(EleTy)) {
// FIXME: We need to track extra state to properly record the size
// of VLAs. Returning UnknownVal here, however, is a stop-gap so that
// we don't have a divide-by-zero below.
return UnknownVal();
}
CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
// If a variable is reinterpreted as a type that doesn't fit into a larger
// type evenly, round it down.
// This is a signed value, since it's used in arithmetic with signed indices.
return svalBuilder.makeIntVal(RegionSize / EleSize,
svalBuilder.getArrayIndexType());
}
//===----------------------------------------------------------------------===//
// Location and region casting.
//===----------------------------------------------------------------------===//