[clang] 208c25f - [clang][dataflow] Add limits to size of modeled data structures in environment.
Yitzhak Mandelbaum via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 24 12:52:28 PST 2022
Author: Yitzhak Mandelbaum
Date: 2022-02-24T20:51:59Z
New Revision: 208c25fcbf483b4dd61fb8b99f8422994cc5072e
URL: https://github.com/llvm/llvm-project/commit/208c25fcbf483b4dd61fb8b99f8422994cc5072e
DIFF: https://github.com/llvm/llvm-project/commit/208c25fcbf483b4dd61fb8b99f8422994cc5072e.diff
LOG: [clang][dataflow] Add limits to size of modeled data structures in environment.
Adds two new parameters to control the size of data structures modeled in the environment: # of values and depth of data structure. The environment already prevents creation of recursive data structures, but that was insufficient in practice. Very large structs still ground the analysis to a halt. These new parameters allow tuning the size more effectively.
In this patch, the parameters are set as internal constants. We leave to a future patch to make these proper model parameters.
Differential Revision: https://reviews.llvm.org/D120510
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 2fb32053a11b5..d82b8b4386d18 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -248,7 +248,8 @@ class Environment {
///
/// `Type` must not be null.
Value *createValueUnlessSelfReferential(QualType Type,
- llvm::DenseSet<QualType> &Visited);
+ llvm::DenseSet<QualType> &Visited,
+ int Depth, int &CreatedValuesCount);
StorageLocation &skip(StorageLocation &Loc, SkipPast SP) const;
const StorageLocation &skip(const StorageLocation &Loc, SkipPast SP) const;
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index fc6f9aa2167b0..fd3f91ddb667e 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -29,6 +29,12 @@
namespace clang {
namespace dataflow {
+// FIXME: convert these to parameters of the analysis or environment. Current
+// settings have been experimentaly validated, but only for a particular
+// analysis.
+static constexpr int MaxCompositeValueDepth = 3;
+static constexpr int MaxCompositeValueSize = 1000;
+
/// Returns a map consisting of key-value entries that are present in both maps.
template <typename K, typename V>
llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
@@ -336,25 +342,40 @@ Value *Environment::getValue(const Expr &E, SkipPast SP) const {
Value *Environment::createValue(QualType Type) {
llvm::DenseSet<QualType> Visited;
- return createValueUnlessSelfReferential(Type, Visited);
+ int CreatedValuesCount = 0;
+ Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
+ CreatedValuesCount);
+ if (CreatedValuesCount > MaxCompositeValueSize) {
+ llvm::errs() << "Attempting to initialize a huge value of type: "
+ << Type.getAsString() << "\n";
+ }
+ return Val;
}
Value *Environment::createValueUnlessSelfReferential(
- QualType Type, llvm::DenseSet<QualType> &Visited) {
+ QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
+ int &CreatedValuesCount) {
assert(!Type.isNull());
+ // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
+ if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
+ Depth > MaxCompositeValueDepth)
+ return nullptr;
+
if (Type->isIntegerType()) {
+ CreatedValuesCount++;
return &takeOwnership(std::make_unique<IntegerValue>());
}
if (Type->isReferenceType()) {
+ CreatedValuesCount++;
QualType PointeeType = Type->getAs<ReferenceType>()->getPointeeType();
auto &PointeeLoc = createStorageLocation(PointeeType);
if (!Visited.contains(PointeeType.getCanonicalType())) {
Visited.insert(PointeeType.getCanonicalType());
- Value *PointeeVal =
- createValueUnlessSelfReferential(PointeeType, Visited);
+ Value *PointeeVal = createValueUnlessSelfReferential(
+ PointeeType, Visited, Depth, CreatedValuesCount);
Visited.erase(PointeeType.getCanonicalType());
if (PointeeVal != nullptr)
@@ -365,13 +386,14 @@ Value *Environment::createValueUnlessSelfReferential(
}
if (Type->isPointerType()) {
+ CreatedValuesCount++;
QualType PointeeType = Type->getAs<PointerType>()->getPointeeType();
auto &PointeeLoc = createStorageLocation(PointeeType);
if (!Visited.contains(PointeeType.getCanonicalType())) {
Visited.insert(PointeeType.getCanonicalType());
- Value *PointeeVal =
- createValueUnlessSelfReferential(PointeeType, Visited);
+ Value *PointeeVal = createValueUnlessSelfReferential(
+ PointeeType, Visited, Depth, CreatedValuesCount);
Visited.erase(PointeeType.getCanonicalType());
if (PointeeVal != nullptr)
@@ -382,6 +404,7 @@ Value *Environment::createValueUnlessSelfReferential(
}
if (Type->isStructureOrClassType()) {
+ CreatedValuesCount++;
// FIXME: Initialize only fields that are accessed in the context that is
// being analyzed.
llvm::DenseMap<const ValueDecl *, Value *> FieldValues;
@@ -394,7 +417,8 @@ Value *Environment::createValueUnlessSelfReferential(
Visited.insert(FieldType.getCanonicalType());
FieldValues.insert(
- {Field, createValueUnlessSelfReferential(FieldType, Visited)});
+ {Field, createValueUnlessSelfReferential(
+ FieldType, Visited, Depth + 1, CreatedValuesCount)});
Visited.erase(FieldType.getCanonicalType());
}
More information about the cfe-commits
mailing list