diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -248,7 +248,8 @@ /// /// `Type` must not be null. Value *createValueUnlessSelfReferential(QualType Type, - llvm::DenseSet &Visited); + llvm::DenseSet &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 --- 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 llvm::DenseMap intersectDenseMaps(const llvm::DenseMap &Map1, @@ -336,25 +342,40 @@ Value *Environment::createValue(QualType Type) { llvm::DenseSet 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 &Visited) { + QualType Type, llvm::DenseSet &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()); } if (Type->isReferenceType()) { + CreatedValuesCount++; QualType PointeeType = Type->getAs()->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 @@ } if (Type->isPointerType()) { + CreatedValuesCount++; QualType PointeeType = Type->getAs()->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 @@ } if (Type->isStructureOrClassType()) { + CreatedValuesCount++; // FIXME: Initialize only fields that are accessed in the context that is // being analyzed. llvm::DenseMap FieldValues; @@ -394,7 +417,8 @@ Visited.insert(FieldType.getCanonicalType()); FieldValues.insert( - {Field, createValueUnlessSelfReferential(FieldType, Visited)}); + {Field, createValueUnlessSelfReferential( + FieldType, Visited, Depth + 1, CreatedValuesCount)}); Visited.erase(FieldType.getCanonicalType()); }