From cb4875a28b1595f31f1eb2d54464f5c3dfc66115 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 11 Jul 2017 21:56:09 +0100 Subject: Issue error properly for oversized arrays for calldata --- libsolidity/analysis/TypeChecker.cpp | 6 ++++++ libsolidity/ast/Types.cpp | 13 ++++++++++++- libsolidity/ast/Types.h | 5 +++++ 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4e5a11ed..56f9c764 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -583,6 +583,12 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) !FunctionType(_variable).interfaceFunctionType() ) m_errorReporter.typeError(_variable.location(), "Internal type is not allowed for public state variables."); + + if (varType->category() == Type::Category::Array) + if (auto arrayType = dynamic_cast(varType.get())) + if ((arrayType->location() == DataLocation::CallData) && !arrayType->validForCalldata()) + m_errorReporter.typeError(_variable.location(), "Array is too large to be encoded as calldata."); + return false; } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index b54407c6..76bfb1a8 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1395,12 +1395,23 @@ bool ArrayType::operator==(Type const& _other) const return isDynamicallySized() || length() == other.length(); } -unsigned ArrayType::calldataEncodedSize(bool _padded) const +bool ArrayType::validForCalldata() const +{ + return unlimitedCalldataEncodedSize(true) <= numeric_limits::max(); +} + +bigint ArrayType::unlimitedCalldataEncodedSize(bool _padded) const { if (isDynamicallySized()) return 32; bigint size = bigint(length()) * (isByteArray() ? 1 : baseType()->calldataEncodedSize(_padded)); size = ((size + 31) / 32) * 32; + return size; +} + +unsigned ArrayType::calldataEncodedSize(bool _padded) const +{ + bigint size = unlimitedCalldataEncodedSize(_padded); solAssert(size <= numeric_limits::max(), "Array size does not fit unsigned."); return unsigned(size); } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index bd5da30a..c24cc11a 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -616,6 +616,9 @@ public: virtual TypePointer interfaceType(bool _inLibrary) const override; virtual bool canBeUsedExternally(bool _inLibrary) const override; + /// @returns true if this is valid to be stored in calldata + bool validForCalldata() const; + /// @returns true if this is a byte array or a string bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; } /// @returns true if this is a string @@ -630,6 +633,8 @@ private: /// String is interpreted as a subtype of Bytes. enum class ArrayKind { Ordinary, Bytes, String }; + bigint unlimitedCalldataEncodedSize(bool _padded) const; + ///< Byte arrays ("bytes") and strings have different semantics from ordinary arrays. ArrayKind m_arrayKind = ArrayKind::Ordinary; TypePointer m_baseType; -- cgit v1.2.3