From 952350bec1207050e1d9477ebae8c7bbd519cebe Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 19 Feb 2015 17:43:53 +0100 Subject: [PATCH] Bugfix for functions override - Functions with byte array type parameters can now be safely overriden. Parameter location is now set at the right place. - Also made a test for the fix --- libsolidity/AST.cpp | 19 ++++--------------- libsolidity/AST.h | 2 +- libsolidity/NameAndTypeResolver.cpp | 8 +++++++- test/SolidityNameAndTypeResolution.cpp | 13 +++++++++++++ 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index c6d8f5c58..761427db4 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -274,15 +274,6 @@ TypePointer FunctionDefinition::getType(ContractDefinition const*) const void FunctionDefinition::checkTypeRequirements() { - // change all byte arrays parameters to point to calldata - if (getVisibility() == Visibility::External) - for (ASTPointer const& var: getParameters()) - { - auto const& type = var->getType(); - solAssert(!!type, ""); - if (auto const* byteArrayType = dynamic_cast(type.get())) - var->setType(byteArrayType->copyForLocation(ByteArrayType::Location::CallData)); - } for (ASTPointer const& var: getParameters() + getReturnParameters()) if (!var->getType()->canLiveOutsideStorage()) BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); @@ -299,16 +290,14 @@ string FunctionDefinition::getCanonicalSignature() const bool VariableDeclaration::isLValue() const { - if (auto const* function = dynamic_cast(getScope())) - if (function->getVisibility() == Declaration::Visibility::External && isFunctionParameter()) - return false; - return true; + // External function parameters are Read-Only + return !isExternalFunctionParameter(); } -bool VariableDeclaration::isFunctionParameter() const +bool VariableDeclaration::isExternalFunctionParameter() const { auto const* function = dynamic_cast(getScope()); - if (!function) + if (!function || function->getVisibility() != Declaration::Visibility::External) return false; for (auto const& variable: function->getParameters()) if (variable.get() == this) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 62855bc7a..64dac594d 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -448,7 +448,7 @@ public: virtual bool isLValue() const override; bool isLocalVariable() const { return !!dynamic_cast(getScope()); } - bool isFunctionParameter() const; + bool isExternalFunctionParameter() const; bool isStateVariable() const { return m_isStateVariable; } bool isIndexed() const { return m_isIndexed; } diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index ea70b65b4..e19b0bf9e 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -333,7 +333,13 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable) // or mapping if (_variable.getTypeName()) { - _variable.setType(_variable.getTypeName()->toType()); + TypePointer type = _variable.getTypeName()->toType(); + // All byte array parameter types should point to call data + if (_variable.isExternalFunctionParameter()) + if (auto const* byteArrayType = dynamic_cast(type.get())) + type = byteArrayType->copyForLocation(ByteArrayType::Location::CallData); + _variable.setType(type); + if (!_variable.getType()) BOOST_THROW_EXCEPTION(_variable.getTypeName()->createTypeError("Invalid type name")); } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index bfef873c4..da6c2a88a 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1163,6 +1163,19 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) +{ + char const* sourceCode = R"( + contract Vehicle { + function f(bytes _a) external returns (uint256 r) {r = 1;} + } + contract Bike is Vehicle { + function f(bytes _a) external returns (uint256 r) {r = 42;} + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNamesWithChecks(sourceCode)); +} + BOOST_AUTO_TEST_SUITE_END() }