[analyzer] DynamicSize: Remove 'getExtent()' from regions

Summary:
This patch introduces a placeholder for representing the dynamic size of
regions. It also moves the `getExtent()` method of `SubRegions` to the
`MemRegionManager` as `getStaticSize()`.

Reviewed By: NoQ

Differential Revision: https://reviews.llvm.org/D69540
This commit is contained in:
Charusso 2020-01-30 16:04:37 +01:00
parent 523896f64a
commit 601687bf73
17 changed files with 230 additions and 152 deletions

View File

@ -0,0 +1,32 @@
//===- DynamicSize.h - Dynamic size related APIs ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines APIs that track and query dynamic size information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZE_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZE_H
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
namespace clang {
namespace ento {
/// Get the stored dynamic size for the region \p MR.
DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
SValBuilder &SVB);
} // namespace ento
} // namespace clang
#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICSIZE_H

View File

@ -112,7 +112,7 @@ public:
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
virtual MemRegionManager* getMemRegionManager() const = 0;
virtual MemRegionManager &getMemRegionManager() const = 0;
const MemSpaceRegion *getMemorySpace() const;
@ -198,14 +198,13 @@ public:
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
protected:
MemRegionManager *Mgr;
MemRegionManager &Mgr;
MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
MemSpaceRegion(MemRegionManager &mgr, Kind k) : MemRegion(k), Mgr(mgr) {
assert(classof(this));
assert(mgr);
}
MemRegionManager* getMemRegionManager() const override { return Mgr; }
MemRegionManager &getMemRegionManager() const override { return Mgr; }
public:
bool isBoundable() const override { return false; }
@ -223,7 +222,7 @@ public:
class CodeSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
CodeSpaceRegion(MemRegionManager *mgr)
CodeSpaceRegion(MemRegionManager &mgr)
: MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
public:
@ -238,7 +237,7 @@ class GlobalsSpaceRegion : public MemSpaceRegion {
virtual void anchor();
protected:
GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {
GlobalsSpaceRegion(MemRegionManager &mgr, Kind k) : MemSpaceRegion(mgr, k) {
assert(classof(this));
}
@ -259,7 +258,7 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
const CodeTextRegion *CR;
StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
StaticGlobalSpaceRegion(MemRegionManager &mgr, const CodeTextRegion *cr)
: GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
assert(cr);
}
@ -286,7 +285,7 @@ class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
void anchor() override;
protected:
NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
NonStaticGlobalSpaceRegion(MemRegionManager &mgr, Kind k)
: GlobalsSpaceRegion(mgr, k) {
assert(classof(this));
}
@ -304,7 +303,7 @@ public:
class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalSystemSpaceRegion(MemRegionManager *mgr)
GlobalSystemSpaceRegion(MemRegionManager &mgr)
: NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
public:
@ -323,7 +322,7 @@ public:
class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalImmutableSpaceRegion(MemRegionManager *mgr)
GlobalImmutableSpaceRegion(MemRegionManager &mgr)
: NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
public:
@ -340,7 +339,7 @@ public:
class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
friend class MemRegionManager;
GlobalInternalSpaceRegion(MemRegionManager *mgr)
GlobalInternalSpaceRegion(MemRegionManager &mgr)
: NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
public:
@ -354,7 +353,7 @@ public:
class HeapSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
HeapSpaceRegion(MemRegionManager *mgr)
HeapSpaceRegion(MemRegionManager &mgr)
: MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
public:
@ -368,7 +367,7 @@ public:
class UnknownSpaceRegion : public MemSpaceRegion {
friend class MemRegionManager;
UnknownSpaceRegion(MemRegionManager *mgr)
UnknownSpaceRegion(MemRegionManager &mgr)
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
public:
@ -385,7 +384,7 @@ class StackSpaceRegion : public MemSpaceRegion {
const StackFrameContext *SFC;
protected:
StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
StackSpaceRegion(MemRegionManager &mgr, Kind k, const StackFrameContext *sfc)
: MemSpaceRegion(mgr, k), SFC(sfc) {
assert(classof(this));
assert(sfc);
@ -405,7 +404,7 @@ public:
class StackLocalsSpaceRegion : public StackSpaceRegion {
friend class MemRegionManager;
StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
StackLocalsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
public:
@ -420,7 +419,7 @@ class StackArgumentsSpaceRegion : public StackSpaceRegion {
private:
friend class MemRegionManager;
StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
StackArgumentsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc)
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
public:
@ -449,12 +448,7 @@ public:
return superRegion;
}
/// getExtent - Returns the size of the region in bytes.
virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
return UnknownVal();
}
MemRegionManager* getMemRegionManager() const override;
MemRegionManager &getMemRegionManager() const override;
bool isSubRegionOf(const MemRegion* R) const override;
@ -491,8 +485,6 @@ public:
bool isBoundable() const override { return true; }
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
void Profile(llvm::FoldingSetNodeID& ID) const override;
void dumpToStream(raw_ostream &os) const override;
@ -552,8 +544,6 @@ public:
return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
}
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
@ -782,8 +772,6 @@ public:
bool isBoundable() const override { return true; }
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
void Profile(llvm::FoldingSetNodeID& ID) const override;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
@ -817,8 +805,6 @@ public:
QualType getValueType() const override { return Str->getType(); }
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
bool isBoundable() const override { return false; }
void Profile(llvm::FoldingSetNodeID& ID) const override {
@ -1021,8 +1007,6 @@ public:
return getDecl()->getType();
}
DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
void dumpToStream(raw_ostream &os) const override;
bool canPrintPretty() const override;
@ -1242,8 +1226,9 @@ const RegionTy* MemRegion::castAs() const {
//===----------------------------------------------------------------------===//
class MemRegionManager {
ASTContext &C;
ASTContext &Ctx;
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
GlobalInternalSpaceRegion *InternalGlobals = nullptr;
@ -1262,13 +1247,18 @@ class MemRegionManager {
CodeSpaceRegion *code = nullptr;
public:
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {}
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : Ctx(c), A(a) {}
~MemRegionManager();
ASTContext &getContext() { return C; }
ASTContext &getContext() { return Ctx; }
llvm::BumpPtrAllocator &getAllocator() { return A; }
/// \returns The static size in bytes of the region \p MR.
/// \note The region \p MR must be a 'SubRegion'.
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR,
SValBuilder &SVB) const;
/// getStackLocalsRegion - Retrieve the memory region associated with the
/// specified stack frame.
const StackLocalsSpaceRegion *
@ -1434,7 +1424,7 @@ private:
//===----------------------------------------------------------------------===//
inline ASTContext &MemRegion::getContext() const {
return getMemRegionManager()->getContext();
return getMemRegionManager().getContext();
}
//===----------------------------------------------------------------------===//

View File

@ -12,13 +12,14 @@
//===----------------------------------------------------------------------===//
#include "Taint.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.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"
@ -175,24 +176,23 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
}
do {
// CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)? If so,
// CHECK UPPER BOUND: Is byteOffset >= size(baseRegion)? If so,
// we are doing a load/store after the last valid offset.
DefinedOrUnknownSVal extentVal =
rawOffset.getRegion()->getExtent(svalBuilder);
if (!extentVal.getAs<NonLoc>())
const MemRegion *MR = rawOffset.getRegion();
DefinedOrUnknownSVal Size = getDynamicSize(state, MR, svalBuilder);
if (!Size.getAs<NonLoc>())
break;
if (extentVal.getAs<nonloc::ConcreteInt>()) {
if (Size.getAs<nonloc::ConcreteInt>()) {
std::pair<NonLoc, nonloc::ConcreteInt> simplifiedOffsets =
getSimplifiedOffsets(rawOffset.getByteOffset(),
extentVal.castAs<nonloc::ConcreteInt>(),
svalBuilder);
Size.castAs<nonloc::ConcreteInt>(), svalBuilder);
rawOffsetVal = simplifiedOffsets.first;
extentVal = simplifiedOffsets.second;
Size = simplifiedOffsets.second;
}
SVal upperbound = svalBuilder.evalBinOpNN(state, BO_GE, rawOffsetVal,
extentVal.castAs<NonLoc>(),
Size.castAs<NonLoc>(),
svalBuilder.getConditionType());
Optional<NonLoc> upperboundToCheck = upperbound.getAs<NonLoc>();

View File

@ -10,12 +10,13 @@
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Basic/Builtins.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
using namespace clang;
using namespace ento;
@ -90,10 +91,10 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
return true; // Return true to model purity.
SValBuilder& svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
DefinedOrUnknownSVal extentMatchesSizeArg =
svalBuilder.evalEQ(state, Extent, Size.castAs<DefinedOrUnknownSVal>());
state = state->assume(extentMatchesSizeArg, true);
DefinedOrUnknownSVal DynSize = getDynamicSize(state, R, svalBuilder);
DefinedOrUnknownSVal DynSizeMatchesSizeArg =
svalBuilder.evalEQ(state, DynSize, Size.castAs<DefinedOrUnknownSVal>());
state = state->assume(DynSizeMatchesSizeArg, true);
assert(state && "The region should not have any previous constraints");
C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));

View File

@ -11,14 +11,15 @@
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "InterCheckerAPI.h"
#include "clang/Basic/CharInfo.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@ -327,10 +328,8 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
// Get the size of the array.
const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
SValBuilder &svalBuilder = C.getSValBuilder();
SVal Extent =
svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal Size =
getDynamicSize(state, superReg, C.getSValBuilder());
// Get the index of the accessed element.
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
@ -935,14 +934,12 @@ bool CStringChecker::IsFirstBufInBound(CheckerContext &C,
// Get the size of the array.
const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
SVal Extent =
svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal SizeDV = getDynamicSize(state, superReg, svalBuilder);
// Get the index of the accessed element.
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize, true);
ProgramStateRef StInBound = state->assumeInBound(Idx, SizeDV, true);
return static_cast<bool>(StInBound);
}
@ -1069,13 +1066,12 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal,
// For now we can only handle the case of offset is 0 and concrete char value.
if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
Offset.getOffset() == 0) {
// Get the base region's extent.
auto *SubReg = cast<SubRegion>(BR);
DefinedOrUnknownSVal Extent = SubReg->getExtent(svalBuilder);
// Get the base region's size.
DefinedOrUnknownSVal SizeDV = getDynamicSize(State, BR, svalBuilder);
ProgramStateRef StateWholeReg, StateNotWholeReg;
std::tie(StateWholeReg, StateNotWholeReg) =
State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
State->assume(svalBuilder.evalEQ(State, SizeDV, *SizeNL));
// With the semantic of 'memset()', we should convert the CharVal to
// unsigned char.

View File

@ -10,12 +10,14 @@
// whether the size of the symbolic region is a multiple of the size of T.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#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"
using namespace clang;
using namespace ento;
@ -109,12 +111,13 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
return;
SValBuilder &svalBuilder = C.getSValBuilder();
SVal extent = SR->getExtent(svalBuilder);
const llvm::APSInt *extentInt = svalBuilder.getKnownValue(state, extent);
if (!extentInt)
DefinedOrUnknownSVal Size = getDynamicSize(state, SR, svalBuilder);
const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
if (!SizeInt)
return;
CharUnits regionSize = CharUnits::fromQuantity(extentInt->getSExtValue());
CharUnits regionSize = CharUnits::fromQuantity(SizeInt->getZExtValue());
CharUnits typeSize = C.getASTContext().getTypeSizeInChars(ToPointeeTy);
// Ignore void, and a few other un-sizeable types.

View File

@ -1,6 +1,7 @@
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "llvm/Support/FormatVariadic.h"
using namespace clang;
@ -42,7 +43,7 @@ SVal PlacementNewChecker::getExtentSizeOfPlace(const Expr *Place,
NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
Offset.getOffset() / C.getASTContext().getCharWidth());
DefinedOrUnknownSVal ExtentInBytes =
BaseRegion->castAs<SubRegion>()->getExtent(SvalBuilder);
getDynamicSize(State, BaseRegion, SvalBuilder);
return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
ExtentInBytes, OffsetInBytes,

View File

@ -13,6 +13,7 @@
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ScopedPrinter.h"
@ -234,8 +235,9 @@ void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
}
ProgramStateRef State = C.getState();
State = State->BindExpr(CE, C.getLocationContext(),
MR->getExtent(C.getSValBuilder()));
DefinedOrUnknownSVal Size = getDynamicSize(State, MR, C.getSValBuilder());
State = State->BindExpr(CE, C.getLocationContext(), Size);
C.addTransition(State);
}

View File

@ -146,7 +146,7 @@ void MPIChecker::allRegionsUsedByWait(
llvm::SmallVector<const MemRegion *, 2> &ReqRegions,
const MemRegion *const MR, const CallEvent &CE, CheckerContext &Ctx) const {
MemRegionManager *const RegionManager = MR->getMemRegionManager();
MemRegionManager &RegionManager = MR->getMemRegionManager();
if (FuncClassifier->isMPI_Waitall(CE.getCalleeIdentifier())) {
const SubRegion *SuperRegion{nullptr};
@ -168,7 +168,7 @@ void MPIChecker::allRegionsUsedByWait(
for (size_t i = 0; i < ArrSize; ++i) {
const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
const ElementRegion *const ER = RegionManager->getElementRegion(
const ElementRegion *const ER = RegionManager.getElementRegion(
CE.getArgExpr(1)->getType()->getPointeeType(), Idx, SuperRegion,
Ctx.getASTContext());

View File

@ -57,6 +57,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@ -1402,15 +1403,16 @@ ProgramStateRef MallocChecker::addExtentSize(CheckerContext &C,
CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType);
if (ElementCount.getAs<NonLoc>()) {
DefinedOrUnknownSVal Extent = Region->getExtent(svalBuilder);
DefinedOrUnknownSVal DynSize = getDynamicSize(State, Region, svalBuilder);
// size in Bytes = ElementCount*TypeSize
SVal SizeInBytes = svalBuilder.evalBinOpNN(
State, BO_Mul, ElementCount.castAs<NonLoc>(),
svalBuilder.makeArrayIndex(TypeSize.getQuantity()),
svalBuilder.getArrayIndexType());
DefinedOrUnknownSVal extentMatchesSize = svalBuilder.evalEQ(
State, Extent, SizeInBytes.castAs<DefinedOrUnknownSVal>());
State = State->assume(extentMatchesSize, true);
DefinedOrUnknownSVal DynSizeMatchesSize = svalBuilder.evalEQ(
State, DynSize, SizeInBytes.castAs<DefinedOrUnknownSVal>());
State = State->assume(DynSizeMatchesSize, true);
}
return State;
}
@ -1542,12 +1544,12 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
return nullptr;
if (Optional<DefinedOrUnknownSVal> DefinedSize =
Size.getAs<DefinedOrUnknownSVal>()) {
SValBuilder &svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
DefinedOrUnknownSVal extentMatchesSize =
svalBuilder.evalEQ(State, Extent, *DefinedSize);
DefinedOrUnknownSVal DynSize = getDynamicSize(State, R, svalBuilder);
State = State->assume(extentMatchesSize, true);
DefinedOrUnknownSVal DynSizeMatchesSize =
svalBuilder.evalEQ(State, DynSize, *DefinedSize);
State = State->assume(DynSizeMatchesSize, true);
assert(State);
}

View File

@ -14,12 +14,13 @@
//===----------------------------------------------------------------------===//
#include "Taint.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/CharUnits.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#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 "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@ -165,13 +166,14 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
SVal ArraySizeVal = svalBuilder.evalBinOpNN(
state, BO_Mul, ArrayLength, EleSizeVal.castAs<NonLoc>(), SizeTy);
// Finally, assume that the array's extent matches the given size.
// Finally, assume that the array's size matches the given size.
const LocationContext *LC = C.getLocationContext();
DefinedOrUnknownSVal Extent =
state->getRegion(VD, LC)->getExtent(svalBuilder);
DefinedOrUnknownSVal DynSize =
getDynamicSize(state, state->getRegion(VD, LC), svalBuilder);
DefinedOrUnknownSVal ArraySize = ArraySizeVal.castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal sizeIsKnown =
svalBuilder.evalEQ(state, Extent, ArraySize);
svalBuilder.evalEQ(state, DynSize, ArraySize);
state = state->assume(sizeIsKnown, true);
// Assume should not fail at this point.

View File

@ -358,7 +358,7 @@ class NoStoreFuncVisitor final : public BugReporterVisitor {
public:
NoStoreFuncVisitor(const SubRegion *R, bugreporter::TrackingKind TKind)
: RegionOfInterest(R), MmrMgr(*R->getMemRegionManager()),
: RegionOfInterest(R), MmrMgr(R->getMemRegionManager()),
SM(MmrMgr.getContext().getSourceManager()),
PP(MmrMgr.getContext().getPrintingPolicy()), TKind(TKind) {}

View File

@ -16,6 +16,7 @@ add_clang_library(clangStaticAnalyzerCore
CommonBugCategories.cpp
ConstraintManager.cpp
CoreEngine.cpp
DynamicSize.cpp
DynamicType.cpp
Environment.cpp
ExplodedGraph.cpp

View File

@ -0,0 +1,30 @@
//===- DynamicSize.cpp - Dynamic size related APIs --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines APIs that track and query dynamic size information.
//
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
namespace clang {
namespace ento {
DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
SValBuilder &SVB) {
return MR->getMemRegionManager().getStaticSize(MR, SVB);
}
} // namespace ento
} // namespace clang

View File

@ -142,7 +142,7 @@ bool SubRegion::isSubRegionOf(const MemRegion* R) const {
return false;
}
MemRegionManager* SubRegion::getMemRegionManager() const {
MemRegionManager &SubRegion::getMemRegionManager() const {
const SubRegion* r = this;
do {
const MemRegion *superRegion = r->getSuperRegion();
@ -159,56 +159,6 @@ const StackFrameContext *VarRegion::getStackFrame() const {
return SSR ? SSR->getStackFrame() : nullptr;
}
//===----------------------------------------------------------------------===//
// Region extents.
//===----------------------------------------------------------------------===//
DefinedOrUnknownSVal TypedValueRegion::getExtent(SValBuilder &svalBuilder) const {
ASTContext &Ctx = svalBuilder.getContext();
QualType T = getDesugaredValueType(Ctx);
if (isa<VariableArrayType>(T))
return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
if (T->isIncompleteType())
return UnknownVal();
CharUnits size = Ctx.getTypeSizeInChars(T);
QualType sizeTy = svalBuilder.getArrayIndexType();
return svalBuilder.makeIntVal(size.getQuantity(), sizeTy);
}
DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const {
// Force callers to deal with bitfields explicitly.
if (getDecl()->isBitField())
return UnknownVal();
DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder);
// A zero-length array at the end of a struct often stands for dynamically-
// allocated extra memory.
if (Extent.isZeroConstant()) {
QualType T = getDesugaredValueType(svalBuilder.getContext());
if (isa<ConstantArrayType>(T))
return UnknownVal();
}
return Extent;
}
DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const {
return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
}
DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const {
return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
}
DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const {
return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1,
svalBuilder.getArrayIndexType());
}
ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
: DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
@ -717,11 +667,78 @@ SourceRange MemRegion::sourceRange() const {
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
static DefinedOrUnknownSVal getTypeSize(QualType Ty, ASTContext &Ctx,
SValBuilder &SVB) {
CharUnits Size = Ctx.getTypeSizeInChars(Ty);
QualType SizeTy = SVB.getArrayIndexType();
return SVB.makeIntVal(Size.getQuantity(), SizeTy);
}
DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
SValBuilder &SVB) const {
const auto *SR = cast<SubRegion>(MR);
SymbolManager &SymMgr = SVB.getSymbolManager();
switch (SR->getKind()) {
case MemRegion::AllocaRegionKind:
case MemRegion::SymbolicRegionKind:
return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
case MemRegion::StringRegionKind:
return SVB.makeIntVal(
cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1,
SVB.getArrayIndexType());
case MemRegion::CompoundLiteralRegionKind:
case MemRegion::CXXBaseObjectRegionKind:
case MemRegion::CXXDerivedObjectRegionKind:
case MemRegion::CXXTempObjectRegionKind:
case MemRegion::CXXThisRegionKind:
case MemRegion::ObjCIvarRegionKind:
case MemRegion::VarRegionKind:
case MemRegion::ElementRegionKind:
case MemRegion::ObjCStringRegionKind: {
QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
if (isa<VariableArrayType>(Ty))
return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
if (Ty->isIncompleteType())
return UnknownVal();
return getTypeSize(Ty, Ctx, SVB);
}
case MemRegion::FieldRegionKind: {
// Force callers to deal with bitfields explicitly.
if (cast<FieldRegion>(SR)->getDecl()->isBitField())
return UnknownVal();
QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
DefinedOrUnknownSVal Size = getTypeSize(Ty, Ctx, SVB);
// A zero-length array at the end of a struct often stands for dynamically
// allocated extra memory.
if (Size.isZeroConstant()) {
if (isa<ConstantArrayType>(Ty))
return UnknownVal();
}
return Size;
}
// FIXME: The following are being used in 'SimpleSValBuilder' and in
// 'ArrayBoundChecker::checkLocation' because there is no symbol to
// represent the regions more appropriately.
case MemRegion::BlockDataRegionKind:
case MemRegion::BlockCodeRegionKind:
case MemRegion::FunctionCodeRegionKind:
return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
default:
llvm_unreachable("Unhandled region");
}
}
template <typename REG>
const REG *MemRegionManager::LazyAllocate(REG*& region) {
if (!region) {
region = A.Allocate<REG>();
new (region) REG(this);
new (region) REG(*this);
}
return region;
@ -746,7 +763,7 @@ MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
return R;
R = A.Allocate<StackLocalsSpaceRegion>();
new (R) StackLocalsSpaceRegion(this, STC);
new (R) StackLocalsSpaceRegion(*this, STC);
return R;
}
@ -759,7 +776,7 @@ MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
return R;
R = A.Allocate<StackArgumentsSpaceRegion>();
new (R) StackArgumentsSpaceRegion(this, STC);
new (R) StackArgumentsSpaceRegion(*this, STC);
return R;
}
@ -781,7 +798,7 @@ const GlobalsSpaceRegion
return R;
R = A.Allocate<StaticGlobalSpaceRegion>();
new (R) StaticGlobalSpaceRegion(this, CR);
new (R) StaticGlobalSpaceRegion(*this, CR);
return R;
}
@ -850,7 +867,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
if (D->hasGlobalStorage() && !D->isStaticLocal()) {
// First handle the globals defined in system headers.
if (C.getSourceManager().isInSystemHeader(D->getLocation())) {
if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) {
// Whitelist the system globals which often DO GET modified, assume the
// rest are immutable.
if (D->getName().find("errno") != StringRef::npos)
@ -914,7 +931,7 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
T = getContext().getBlockPointerType(T);
const BlockCodeRegion *BTR =
getBlockCodeRegion(BD, C.getCanonicalType(T),
getBlockCodeRegion(BD, Ctx.getCanonicalType(T),
STC->getAnalysisDeclContext());
sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
BTR);
@ -1476,7 +1493,7 @@ RegionOffset MemRegion::getAsOffset() const {
std::pair<const VarRegion *, const VarRegion *>
BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
MemRegionManager &MemMgr = *getMemRegionManager();
MemRegionManager &MemMgr = getMemRegionManager();
const VarRegion *VR = nullptr;
const VarRegion *OriginalVR = nullptr;
@ -1511,7 +1528,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() {
return;
}
MemRegionManager &MemMgr = *getMemRegionManager();
MemRegionManager &MemMgr = getMemRegionManager();
llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
BumpVectorContext BC(A);

View File

@ -23,6 +23,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
@ -876,7 +877,7 @@ collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
// Find the length (in bits) of the region being invalidated.
uint64_t Length = UINT64_MAX;
SVal Extent = Top->getExtent(SVB);
SVal Extent = Top->getMemRegionManager().getStaticSize(Top, SVB);
if (Optional<nonloc::ConcreteInt> ExtentCI =
Extent.getAs<nonloc::ConcreteInt>()) {
const llvm::APSInt &ExtentInt = ExtentCI->getValue();
@ -1394,7 +1395,7 @@ DefinedOrUnknownSVal
RegionStoreManager::getSizeInElements(ProgramStateRef state,
const MemRegion *R,
QualType EleTy) {
SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
DefinedOrUnknownSVal Size = getDynamicSize(state, R, svalBuilder);
const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
if (!SizeInt)
return UnknownVal();

View File

@ -329,7 +329,7 @@ QualType SymbolDerived::getType() const {
}
QualType SymbolExtent::getType() const {
ASTContext &Ctx = R->getMemRegionManager()->getContext();
ASTContext &Ctx = R->getMemRegionManager().getContext();
return Ctx.getSizeType();
}