diff options
-rw-r--r-- | libsolidity/ast/Types.cpp | 4 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 5 | ||||
-rw-r--r-- | libsolidity/codegen/ArrayUtils.cpp | 2 | ||||
-rw-r--r-- | libsolidity/codegen/Compiler.h | 7 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerUtils.cpp | 2 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 31 |
7 files changed, 39 insertions, 14 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0253e843..cb97eae8 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -781,7 +781,7 @@ bool ArrayType::operator==(Type const& _other) const unsigned ArrayType::calldataEncodedSize(bool _padded) const { if (isDynamicallySized()) - return 0; + return 32; bigint size = bigint(length()) * (isByteArray() ? 1 : baseType()->calldataEncodedSize(_padded)); size = ((size + 31) / 32) * 32; solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned."); @@ -1698,7 +1698,7 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary) const TypePointers returnParameterTypes; vector<string> returnParameterNames; for (size_t i = 0; i < m_returnParameterTypes.size(); ++i) - if (m_returnParameterTypes[i]->calldataEncodedSize() > 0) + if (!m_returnParameterTypes[i]->isDynamicallySized()) { returnParameterTypes.push_back(m_returnParameterTypes[i]); returnParameterNames.push_back(m_returnParameterNames[i]); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 59c84b7a..f5aefa25 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -175,8 +175,9 @@ public: virtual bool operator==(Type const& _other) const { return category() == _other.category(); } virtual bool operator!=(Type const& _other) const { return !this->operator ==(_other); } - /// @returns number of bytes used by this type when encoded for CALL, or 0 if the encoding - /// is not a simple big-endian encoding or the type cannot be stored in calldata. + /// @returns number of bytes used by this type when encoded for CALL. If it is a dynamic type, + /// returns the size of the pointer (usually 32). Returns 0 if the type cannot be encoded + /// in calldata. /// If @a _padded then it is assumed that each element is padded to a multiple of 32 bytes. virtual unsigned calldataEncodedSize(bool _padded) const { (void)_padded; return 0; } /// @returns the size of this data type in bytes when stored in memory. For memory-reference diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index ba26caa6..f1acce31 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -271,7 +271,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const { solAssert( - _sourceType.baseType()->calldataEncodedSize() > 0, + !_sourceType.baseType()->isDynamicallySized(), "Nested dynamic arrays not implemented here." ); CompilerUtils utils(m_context); diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 14314434..9d069f7c 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -92,13 +92,6 @@ private: void registerStateVariables(ContractDefinition const& _contract); void initializeStateVariables(ContractDefinition const& _contract); - /// Initialises all memory arrays in the local variables to point to an empty location. - void initialiseMemoryArrays(std::vector<VariableDeclaration const*> _variables); - /// Pushes the initialised value of the given type to the stack. If the type is a memory - /// reference type, allocates memory and pushes the memory pointer. - /// Not to be used for storage references. - void initialiseInMemory(Type const& _type); - virtual bool visit(VariableDeclaration const& _variableDeclaration) override; virtual bool visit(FunctionDefinition const& _function) override; virtual bool visit(IfStatement const& _ifStatement) override; diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index ce20f2d1..2ebf5b64 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -613,7 +613,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } } -void CompilerUtils::pushZeroValue(const Type& _type) +void CompilerUtils::pushZeroValue(Type const& _type) { auto const* referenceType = dynamic_cast<ReferenceType const*>(&_type); if (!referenceType || referenceType->location() == DataLocation::Storage) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 05d9ea1c..1a089d63 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1226,7 +1226,7 @@ void ExpressionCompiler::appendExternalFunctionCall( else for (auto const& retType: _functionType.returnParameterTypes()) { - solAssert(retType->calldataEncodedSize() > 0, "Unable to return dynamic type from external call."); + solAssert(!retType->isDynamicallySized(), "Unable to return dynamic type from external call."); retSize += retType->calldataEncodedSize(); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 20fef48d..93b42c51 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5849,6 +5849,37 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod) compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0))); } + +BOOST_AUTO_TEST_CASE(string_allocation_bug) +{ + char const* sourceCode = R"( + contract Sample + { + struct s { uint16 x; uint16 y; string a; string b;} + s[2] public p; + function Sample() { + s memory m; + m.x = 0xbbbb; + m.y = 0xcccc; + m.a = "hello"; + m.b = "world"; + p[0] = m; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("p(uint256)") == encodeArgs( + u256(0xbbbb), + u256(0xcccc), + u256(0x80), + u256(0xc0), + u256(5), + string("hello"), + u256(5), + string("world") + )); +} + BOOST_AUTO_TEST_SUITE_END() } |