mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9432 from ethereum/develop
Merge develop into breaking.
This commit is contained in:
+20
-41
@@ -63,37 +63,6 @@ struct TypeComp
|
||||
};
|
||||
using TypeSet = std::set<Type const*, TypeComp>;
|
||||
|
||||
bigint storageSizeUpperBoundInner(
|
||||
Type const& _type,
|
||||
set<StructDefinition const*>& _structsSeen
|
||||
)
|
||||
{
|
||||
switch (_type.category())
|
||||
{
|
||||
case Type::Category::Array:
|
||||
{
|
||||
auto const& t = dynamic_cast<ArrayType const&>(_type);
|
||||
if (!t.isDynamicallySized())
|
||||
return storageSizeUpperBoundInner(*t.baseType(), _structsSeen) * t.length();
|
||||
break;
|
||||
}
|
||||
case Type::Category::Struct:
|
||||
{
|
||||
auto const& t = dynamic_cast<StructType const&>(_type);
|
||||
solAssert(!_structsSeen.count(&t.structDefinition()), "Recursive struct.");
|
||||
bigint size = 1;
|
||||
_structsSeen.insert(&t.structDefinition());
|
||||
for (auto const& m: t.members(nullptr))
|
||||
size += storageSizeUpperBoundInner(*m.type, _structsSeen);
|
||||
_structsSeen.erase(&t.structDefinition());
|
||||
return size;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return bigint(1);
|
||||
}
|
||||
|
||||
void oversizedSubtypesInner(
|
||||
Type const& _type,
|
||||
bool _includeType,
|
||||
@@ -106,7 +75,7 @@ void oversizedSubtypesInner(
|
||||
case Type::Category::Array:
|
||||
{
|
||||
auto const& t = dynamic_cast<ArrayType const&>(_type);
|
||||
if (_includeType && storageSizeUpperBound(t) >= bigint(1) << 64)
|
||||
if (_includeType && t.storageSizeUpperBound() >= bigint(1) << 64)
|
||||
_oversizedSubtypes.insert(&t);
|
||||
oversizedSubtypesInner(*t.baseType(), t.isDynamicallySized(), _structsSeen, _oversizedSubtypes);
|
||||
break;
|
||||
@@ -116,7 +85,7 @@ void oversizedSubtypesInner(
|
||||
auto const& t = dynamic_cast<StructType const&>(_type);
|
||||
if (_structsSeen.count(&t.structDefinition()))
|
||||
return;
|
||||
if (_includeType && storageSizeUpperBound(t) >= bigint(1) << 64)
|
||||
if (_includeType && t.storageSizeUpperBound() >= bigint(1) << 64)
|
||||
_oversizedSubtypes.insert(&t);
|
||||
_structsSeen.insert(&t.structDefinition());
|
||||
for (auto const& m: t.members(nullptr))
|
||||
@@ -231,12 +200,6 @@ util::Result<TypePointers> transformParametersToExternal(TypePointers const& _pa
|
||||
|
||||
}
|
||||
|
||||
bigint solidity::frontend::storageSizeUpperBound(frontend::Type const& _type)
|
||||
{
|
||||
set<StructDefinition const*> structsSeen;
|
||||
return storageSizeUpperBoundInner(_type, structsSeen);
|
||||
}
|
||||
|
||||
vector<frontend::Type const*> solidity::frontend::oversizedSubtypes(frontend::Type const& _type)
|
||||
{
|
||||
set<StructDefinition const*> structsSeen;
|
||||
@@ -1867,7 +1830,7 @@ BoolResult ArrayType::validForLocation(DataLocation _loc) const
|
||||
break;
|
||||
}
|
||||
case DataLocation::Storage:
|
||||
if (storageSizeUpperBound(*this) >= bigint(1) << 256)
|
||||
if (storageSizeUpperBound() >= bigint(1) << 256)
|
||||
return BoolResult::err("Type too large for storage.");
|
||||
break;
|
||||
}
|
||||
@@ -1908,6 +1871,14 @@ bool ArrayType::isDynamicallyEncoded() const
|
||||
return isDynamicallySized() || baseType()->isDynamicallyEncoded();
|
||||
}
|
||||
|
||||
bigint ArrayType::storageSizeUpperBound() const
|
||||
{
|
||||
if (isDynamicallySized())
|
||||
return 1;
|
||||
else
|
||||
return length() * baseType()->storageSizeUpperBound();
|
||||
}
|
||||
|
||||
u256 ArrayType::storageSize() const
|
||||
{
|
||||
if (isDynamicallySized())
|
||||
@@ -2381,6 +2352,14 @@ u256 StructType::memoryDataSize() const
|
||||
return size;
|
||||
}
|
||||
|
||||
bigint StructType::storageSizeUpperBound() const
|
||||
{
|
||||
bigint size = 1;
|
||||
for (auto const& member: members(nullptr))
|
||||
size += member.type->storageSizeUpperBound();
|
||||
return size;
|
||||
}
|
||||
|
||||
u256 StructType::storageSize() const
|
||||
{
|
||||
return max<u256>(1, members(nullptr).storageSize());
|
||||
@@ -2558,7 +2537,7 @@ BoolResult StructType::validForLocation(DataLocation _loc) const
|
||||
|
||||
if (
|
||||
_loc == DataLocation::Storage &&
|
||||
storageSizeUpperBound(*this) >= bigint(1) << 256
|
||||
storageSizeUpperBound() >= bigint(1) << 256
|
||||
)
|
||||
return BoolResult::err("Type too large for storage.");
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ using BoolResult = util::Result<bool>;
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
bigint storageSizeUpperBound(frontend::Type const& _type);
|
||||
std::vector<frontend::Type const*> oversizedSubtypes(frontend::Type const& _type);
|
||||
|
||||
inline rational makeRational(bigint const& _numerator, bigint const& _denominator)
|
||||
@@ -251,6 +250,10 @@ public:
|
||||
/// @returns the number of storage slots required to hold this value in storage.
|
||||
/// For dynamically "allocated" types, it returns the size of the statically allocated head,
|
||||
virtual u256 storageSize() const { return 1; }
|
||||
/// @returns an upper bound on the total storage size required by this type, descending
|
||||
/// into structs and statically-sized arrays. This is mainly to ensure that the storage
|
||||
/// slot allocation algorithm does not overflow, it is not a protection against collisions.
|
||||
virtual bigint storageSizeUpperBound() const { return 1; }
|
||||
/// Multiple small types can be packed into a single storage slot. If such a packing is possible
|
||||
/// this function @returns the size in bytes smaller than 32. Data is moved to the next slot if
|
||||
/// it does not fit.
|
||||
@@ -790,6 +793,7 @@ public:
|
||||
unsigned calldataEncodedTailSize() const override;
|
||||
bool isDynamicallySized() const override { return m_hasDynamicLength; }
|
||||
bool isDynamicallyEncoded() const override;
|
||||
bigint storageSizeUpperBound() const override;
|
||||
u256 storageSize() const override;
|
||||
bool containsNestedMapping() const override { return m_baseType->containsNestedMapping(); }
|
||||
bool nameable() const override { return true; }
|
||||
@@ -954,6 +958,7 @@ public:
|
||||
unsigned calldataEncodedTailSize() const override;
|
||||
bool isDynamicallyEncoded() const override;
|
||||
u256 memoryDataSize() const override;
|
||||
bigint storageSizeUpperBound() const override;
|
||||
u256 storageSize() const override;
|
||||
bool containsNestedMapping() const override;
|
||||
bool nameable() const override { return true; }
|
||||
|
||||
Reference in New Issue
Block a user