From 0b65b2dff64bdc6d71df94a13f89b7b1119b13b1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 9 Aug 2018 01:24:52 +0200 Subject: Disallow packed encoding of arrays of structs. --- libsolidity/ast/Types.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 2dcfda42..5368e9c2 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -400,17 +400,17 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _p encodingType = encodingType->interfaceType(_inLibraryCall); if (encodingType) encodingType = encodingType->encodingType(); - if (auto structType = dynamic_cast(encodingType.get())) - { - // Structs are fine in the following circumstances: - // - ABIv2 without packed encoding or, - // - storage struct for a library - if (!( - (_encoderV2 && !_packed) || - (structType->location() == DataLocation::Storage && _inLibraryCall) - )) + // Structs are fine in the following circumstances: + // - ABIv2 without packed encoding or, + // - storage struct for a library + if (_inLibraryCall && encodingType->dataStoredIn(DataLocation::Storage)) + return encodingType; + TypePointer baseType = encodingType; + while (auto const* arrayType = dynamic_cast(baseType.get())) + baseType = arrayType->baseType(); + if (dynamic_cast(baseType.get())) + if (!_encoderV2 || _packed) return TypePointer(); - } return encodingType; } -- cgit From 7d7abeb1496dddfab7eb8705dbfc3d06284cf25d Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 6 Aug 2018 14:59:37 +0200 Subject: Disallow ambiguous conversions between number literals and bytesXX types. --- libsolidity/ast/Types.cpp | 55 ++++++++++++++++++++++++++++++----------------- libsolidity/ast/Types.h | 15 +++++++++---- 2 files changed, 46 insertions(+), 24 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 2dcfda42..349e4a02 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -355,13 +355,7 @@ TypePointer Type::forLiteral(Literal const& _literal) case Token::FalseLiteral: return make_shared(); case Token::Number: - { - tuple validLiteral = RationalNumberType::isValidLiteral(_literal); - if (get<0>(validLiteral) == true) - return make_shared(get<1>(validLiteral)); - else - return TypePointer(); - } + return RationalNumberType::forLiteral(_literal); case Token::StringLiteral: return make_shared(_literal); default: @@ -779,6 +773,30 @@ tuple RationalNumberType::parseRational(string const& _value) } } +TypePointer RationalNumberType::forLiteral(Literal const& _literal) +{ + solAssert(_literal.token() == Token::Number, ""); + tuple validLiteral = isValidLiteral(_literal); + if (get<0>(validLiteral)) + { + TypePointer compatibleBytesType; + if (_literal.isHexNumber()) + { + size_t digitCount = count_if( + _literal.value().begin() + 2, // skip "0x" + _literal.value().end(), + [](unsigned char _c) -> bool { return isxdigit(_c); } + ); + // require even number of digits + if (!(digitCount & 1)) + compatibleBytesType = make_shared(digitCount / 2); + } + + return make_shared(get<1>(validLiteral), compatibleBytesType); + } + return TypePointer(); +} + tuple RationalNumberType::isValidLiteral(Literal const& _literal) { rational value; @@ -918,14 +936,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const return false; } case Category::FixedBytes: - { - FixedBytesType const& fixedBytes = dynamic_cast(_convertTo); - if (isFractional()) - return false; - if (integerType()) - return fixedBytes.numBytes() * 8 >= integerType()->numBits(); - return false; - } + return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo); default: return false; } @@ -933,11 +944,15 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - TypePointer mobType = mobileType(); - return - (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) || - (!isFractional() && _convertTo.category() == Category::FixedBytes) - ; + if (isImplicitlyConvertibleTo(_convertTo)) + return true; + else if (_convertTo.category() != Category::FixedBytes) + { + TypePointer mobType = mobileType(); + return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)); + } + else + return false; } TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3b57109d..8bae3d41 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -423,12 +423,12 @@ public: virtual Category category() const override { return Category::RationalNumber; } - /// @returns true if the literal is a valid integer. - static std::tuple isValidLiteral(Literal const& _literal); + static TypePointer forLiteral(Literal const& _literal); - explicit RationalNumberType(rational const& _value): - m_value(_value) + explicit RationalNumberType(rational const& _value, TypePointer const& _compatibleBytesType = TypePointer()): + m_value(_value), m_compatibleBytesType(_compatibleBytesType) {} + virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; @@ -462,6 +462,13 @@ public: private: rational m_value; + /// Bytes type to which the rational can be explicitly converted. + /// Empty for all rationals that are not directly parsed from hex literals. + TypePointer m_compatibleBytesType; + + /// @returns true if the literal is a valid integer. + static std::tuple isValidLiteral(Literal const& _literal); + /// @returns true if the literal is a valid rational number. static std::tuple parseRational(std::string const& _value); -- cgit From 43bda534102c95a85daddc64fb466eb8c88e2325 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 8 Aug 2018 14:46:17 +0200 Subject: Fixes issue where computing storage size for a number would take too long. Fixes #4673. --- libsolidity/ast/Types.cpp | 3 ++- libsolidity/ast/Types.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 2dcfda42..21631693 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1263,7 +1263,8 @@ shared_ptr RationalNumberType::fixedPointType() const return shared_ptr(); // This means we round towards zero for positive and negative values. bigint v = value.numerator() / value.denominator(); - if (negative) + + if (negative && v != 0) // modify value to satisfy bit requirements for negative numbers: // add one bit for sign and decrement because negative numbers can be larger v = (v - 1) << 1; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3b57109d..787c9360 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -446,7 +446,8 @@ public: /// @returns the smallest integer type that can hold the value or an empty pointer if not possible. std::shared_ptr integerType() const; - /// @returns the smallest fixed type that can hold the value or incurs the least precision loss. + /// @returns the smallest fixed type that can hold the value or incurs the least precision loss, + /// unless the value was truncated, then a suitable type will be chosen to indicate such event. /// If the integer part does not fit, returns an empty pointer. std::shared_ptr fixedPointType() const; -- cgit From c05911914550388d7a28563096e3b9772f1b9d23 Mon Sep 17 00:00:00 2001 From: Jesse Busman Date: Thu, 28 Jun 2018 13:31:23 +0200 Subject: Add implicit convertibility to function pointer with higher state mutability --- libsolidity/ast/Types.cpp | 79 +++++++++++++++++++++++++++++++++++------------ libsolidity/ast/Types.h | 7 ++++- 2 files changed, 65 insertions(+), 21 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0d69ae1a..9e815ca8 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2569,28 +2569,10 @@ bool FunctionType::operator==(Type const& _other) const { if (_other.category() != category()) return false; - FunctionType const& other = dynamic_cast(_other); - if ( - m_kind != other.m_kind || - m_stateMutability != other.stateMutability() || - m_parameterTypes.size() != other.m_parameterTypes.size() || - m_returnParameterTypes.size() != other.m_returnParameterTypes.size() - ) - return false; - - auto typeCompare = [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; }; - if ( - !equal(m_parameterTypes.cbegin(), m_parameterTypes.cend(), other.m_parameterTypes.cbegin(), typeCompare) || - !equal(m_returnParameterTypes.cbegin(), m_returnParameterTypes.cend(), other.m_returnParameterTypes.cbegin(), typeCompare) - ) - return false; - //@todo this is ugly, but cannot be prevented right now - if (m_gasSet != other.m_gasSet || m_valueSet != other.m_valueSet) - return false; - if (bound() != other.bound()) + if (!equalExcludingStateMutability(other)) return false; - if (bound() && *selfType() != *other.selfType()) + if (m_stateMutability != other.stateMutability()) return false; return true; } @@ -2606,6 +2588,31 @@ bool FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const return _convertTo.category() == category(); } +bool FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const +{ + if (_convertTo.category() != category()) + return false; + + FunctionType const& convertTo = dynamic_cast(_convertTo); + + if (!equalExcludingStateMutability(convertTo)) + return false; + + // non-payable should not be convertible to payable + if (m_stateMutability != StateMutability::Payable && convertTo.stateMutability() == StateMutability::Payable) + return false; + + // payable should be convertible to non-payable, because you are free to pay 0 ether + if (m_stateMutability == StateMutability::Payable && convertTo.stateMutability() == StateMutability::NonPayable) + return true; + + // e.g. pure should be convertible to view, but not the other way around. + if (m_stateMutability > convertTo.stateMutability()) + return false; + + return true; +} + TypePointer FunctionType::unaryOperatorResult(Token::Value _operator) const { if (_operator == Token::Value::Delete) @@ -2863,6 +2870,38 @@ bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const ); } +bool FunctionType::hasEqualReturnTypes(FunctionType const& _other) const +{ + if (m_returnParameterTypes.size() != _other.m_returnParameterTypes.size()) + return false; + return equal( + m_returnParameterTypes.cbegin(), + m_returnParameterTypes.cend(), + _other.m_returnParameterTypes.cbegin(), + [](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; } + ); +} + +bool FunctionType::equalExcludingStateMutability(FunctionType const& _other) const +{ + if (m_kind != _other.m_kind) + return false; + + if (!hasEqualParameterTypes(_other) || !hasEqualReturnTypes(_other)) + return false; + + //@todo this is ugly, but cannot be prevented right now + if (m_gasSet != _other.m_gasSet || m_valueSet != _other.m_valueSet) + return false; + + if (bound() != _other.bound()) + return false; + + solAssert(!bound() || *selfType() == *_other.selfType(), ""); + + return true; +} + bool FunctionType::isBareCall() const { switch (m_kind) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 8bae3d41..cc96ac4b 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1012,6 +1012,7 @@ public: virtual std::string richIdentifier() const override; virtual bool operator==(Type const& _other) const override; + virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override; @@ -1041,8 +1042,12 @@ public: /// @param _selfType if the function is bound, this has to be supplied and is the type of the /// expression the function is called on. bool canTakeArguments(TypePointers const& _arguments, TypePointer const& _selfType = TypePointer()) const; - /// @returns true if the types of parameters are equal (doesn't check return parameter types) + /// @returns true if the types of parameters are equal (does not check return parameter types) bool hasEqualParameterTypes(FunctionType const& _other) const; + /// @returns true iff the return types are equal (does not check parameter types) + bool hasEqualReturnTypes(FunctionType const& _other) const; + /// @returns true iff the function type is equal to the given type, ignoring state mutability differences. + bool equalExcludingStateMutability(FunctionType const& _other) const; /// @returns true if the ABI is used for this call (only meaningful for external calls) bool isBareCall() const; -- cgit From 683bce18690cc2790b68289278a5d84995472fda Mon Sep 17 00:00:00 2001 From: Chase McDermott Date: Tue, 7 Aug 2018 15:58:34 +0200 Subject: Refactor data location check. --- libsolidity/ast/AST.cpp | 121 ++++++++++++++++++++++++++++++++++++++++-------- libsolidity/ast/AST.h | 16 +++++++ 2 files changed, 118 insertions(+), 19 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 23797d52..a376e55d 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -418,6 +418,7 @@ bool VariableDeclaration::isLocalVariable() const { auto s = scope(); return + dynamic_cast(s) || dynamic_cast(s) || dynamic_cast(s) || dynamic_cast(s); @@ -425,14 +426,18 @@ bool VariableDeclaration::isLocalVariable() const bool VariableDeclaration::isCallableParameter() const { - auto const* callable = dynamic_cast(scope()); - if (!callable) - return false; - for (auto const& variable: callable->parameters()) - if (variable.get() == this) - return true; - if (callable->returnParameterList()) - for (auto const& variable: callable->returnParameterList()->parameters()) + if (isReturnParameter()) + return true; + + vector> const* parameters = nullptr; + + if (auto const* funTypeName = dynamic_cast(scope())) + parameters = &funTypeName->parameterTypes(); + else if (auto const* callable = dynamic_cast(scope())) + parameters = &callable->parameters(); + + if (parameters) + for (auto const& variable: *parameters) if (variable.get() == this) return true; return false; @@ -445,11 +450,16 @@ bool VariableDeclaration::isLocalOrReturn() const bool VariableDeclaration::isReturnParameter() const { - auto const* callable = dynamic_cast(scope()); - if (!callable) - return false; - if (callable->returnParameterList()) - for (auto const& variable: callable->returnParameterList()->parameters()) + vector> const* returnParameters = nullptr; + + if (auto const* funTypeName = dynamic_cast(scope())) + returnParameters = &funTypeName->returnParameterTypes(); + else if (auto const* callable = dynamic_cast(scope())) + if (callable->returnParameterList()) + returnParameters = &callable->returnParameterList()->parameters(); + + if (returnParameters) + for (auto const& variable: *returnParameters) if (variable.get() == this) return true; return false; @@ -457,15 +467,88 @@ bool VariableDeclaration::isReturnParameter() const bool VariableDeclaration::isExternalCallableParameter() const { - auto const* callable = dynamic_cast(scope()); - if (!callable || callable->visibility() != Declaration::Visibility::External) + if (!isCallableParameter()) return false; - for (auto const& variable: callable->parameters()) - if (variable.get() == this) - return true; + + if (auto const* callable = dynamic_cast(scope())) + if (callable->visibility() == Declaration::Visibility::External) + return !isReturnParameter(); + return false; } +bool VariableDeclaration::isInternalCallableParameter() const +{ + if (!isCallableParameter()) + return false; + + if (auto const* funTypeName = dynamic_cast(scope())) + return funTypeName->visibility() == Declaration::Visibility::Internal; + else if (auto const* callable = dynamic_cast(scope())) + return callable->visibility() <= Declaration::Visibility::Internal; + return false; +} + +bool VariableDeclaration::isLibraryFunctionParameter() const +{ + if (!isCallableParameter()) + return false; + if (auto const* funDef = dynamic_cast(scope())) + return dynamic_cast(*funDef->scope()).isLibrary(); + else + return false; +} + +bool VariableDeclaration::isEventParameter() const +{ + return dynamic_cast(scope()) != nullptr; +} + +bool VariableDeclaration::hasReferenceOrMappingType() const +{ + solAssert(typeName(), ""); + solAssert(typeName()->annotation().type, "Can only be called after reference resolution"); + TypePointer const& type = typeName()->annotation().type; + return type->category() == Type::Category::Mapping || dynamic_cast(type.get()); +} + +set VariableDeclaration::allowedDataLocations() const +{ + using Location = VariableDeclaration::Location; + + if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter()) + return set{ Location::Default }; + else if (isStateVariable() && isConstant()) + return set{ Location::Memory }; + else if (isExternalCallableParameter()) + { + set locations{ Location::CallData }; + if (isLibraryFunctionParameter()) + locations.insert(Location::Storage); + return locations; + } + else if (isCallableParameter()) + { + set locations{ Location::Memory }; + if (isInternalCallableParameter() || isLibraryFunctionParameter()) + locations.insert(Location::Storage); + return locations; + } + else if (isLocalVariable()) + { + solAssert(typeName(), ""); + solAssert(typeName()->annotation().type, "Can only be called after reference resolution"); + if (typeName()->annotation().type->category() == Type::Category::Mapping) + return set{ Location::Storage }; + else + // TODO: add Location::Calldata once implemented for local variables. + return set{ Location::Memory, Location::Storage }; + } + else + // Struct members etc. + return set{ Location::Default }; +} + TypePointer VariableDeclaration::type() const { return annotation().type; @@ -580,7 +663,7 @@ bool Literal::passesAddressChecksum() const return dev::passesAddressChecksum(value(), true); } -std::string Literal::getChecksummedAddress() const +string Literal::getChecksummedAddress() const { solAssert(isHexNumber(), "Expected hex number"); /// Pad literal to be a proper hex address. diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 69c6fa05..b953211d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -685,6 +685,8 @@ public: virtual bool isLValue() const override; virtual bool isPartOfExternalInterface() const override { return isPublic(); } + /// @returns true iff this variable is the parameter (or return parameter) of a function + /// (or function type name or event) or declared inside a function body. bool isLocalVariable() const; /// @returns true if this variable is a parameter or return parameter of a function. bool isCallableParameter() const; @@ -693,13 +695,27 @@ public: /// @returns true if this variable is a local variable or return parameter. bool isLocalOrReturn() const; /// @returns true if this variable is a parameter (not return parameter) of an external function. + /// This excludes parameters of external function type names. bool isExternalCallableParameter() const; + /// @returns true if this variable is a parameter or return parameter of an internal function + /// or a function type of internal visibility. + bool isInternalCallableParameter() const; + /// @returns true iff this variable is a parameter(or return parameter of a library function + bool isLibraryFunctionParameter() const; /// @returns true if the type of the variable does not need to be specified, i.e. it is declared /// in the body of a function or modifier. + /// @returns true if this variable is a parameter of an event. + bool isEventParameter() const; + /// @returns true if the type of the variable is a reference or mapping type, i.e. + /// array, struct or mapping. These types can take a data location (and often require it). + /// Can only be called after reference resolution. + bool hasReferenceOrMappingType() const; bool isStateVariable() const { return m_isStateVariable; } bool isIndexed() const { return m_isIndexed; } bool isConstant() const { return m_isConstant; } Location referenceLocation() const { return m_location; } + /// @returns a set of allowed storage locations for the variable. + std::set allowedDataLocations() const; virtual TypePointer type() const override; -- cgit From 9328ea4c3c023950e59405941cfc25ec4c0ed1b4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 30 Jun 2018 18:09:13 +0200 Subject: Add abi.decode(bytes data, (...)) --- libsolidity/ast/Types.cpp | 13 ++++++++++++- libsolidity/ast/Types.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 68c201a8..c9dca126 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2553,6 +2553,7 @@ string FunctionType::richIdentifier() const case Kind::ABIEncodePacked: id += "abiencodepacked"; break; case Kind::ABIEncodeWithSelector: id += "abiencodewithselector"; break; case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break; + case Kind::ABIDecode: id += "abidecode"; break; default: solAssert(false, "Unknown function location."); break; } id += "_" + stateMutabilityToString(m_stateMutability); @@ -2959,7 +2960,8 @@ bool FunctionType::isPure() const m_kind == Kind::ABIEncode || m_kind == Kind::ABIEncodePacked || m_kind == Kind::ABIEncodeWithSelector || - m_kind == Kind::ABIEncodeWithSignature; + m_kind == Kind::ABIEncodeWithSignature || + m_kind == Kind::ABIDecode; } TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) @@ -3315,6 +3317,15 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const FunctionType::Kind::ABIEncodeWithSignature, true, StateMutability::Pure + )}, + {"decode", make_shared( + TypePointers(), + TypePointers(), + strings{}, + strings{}, + FunctionType::Kind::ABIDecode, + true, + StateMutability::Pure )} }); default: diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 34f862c3..d8e73ab9 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -934,6 +934,7 @@ public: ABIEncodePacked, ABIEncodeWithSelector, ABIEncodeWithSignature, + ABIDecode, GasLeft ///< gasleft() }; -- cgit From 7ca0aaaf6f62aafd0fe36ae6b7dc777361ae40e3 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 15 Aug 2018 14:40:20 +0200 Subject: Add ``staticcall`` to ``address``. --- libsolidity/ast/Types.cpp | 6 ++++++ libsolidity/ast/Types.h | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c9dca126..ccf31543 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -621,6 +621,7 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons {"callcode", make_shared(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, {"delegatecall", make_shared(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, false)}, {"send", make_shared(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}, + {"staticcall", make_shared(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, {"transfer", make_shared(strings{"uint"}, strings(), FunctionType::Kind::Transfer)} }; else @@ -2522,6 +2523,7 @@ string FunctionType::richIdentifier() const case Kind::BareCall: id += "barecall"; break; case Kind::BareCallCode: id += "barecallcode"; break; case Kind::BareDelegateCall: id += "baredelegatecall"; break; + case Kind::BareStaticCall: id += "barestaticcall"; break; case Kind::Creation: id += "creation"; break; case Kind::Send: id += "send"; break; case Kind::Transfer: id += "transfer"; break; @@ -2705,6 +2707,7 @@ unsigned FunctionType::sizeOnStack() const case Kind::BareCall: case Kind::BareCallCode: case Kind::BareDelegateCall: + case Kind::BareStaticCall: case Kind::Internal: case Kind::ArrayPush: case Kind::ArrayPop: @@ -2772,6 +2775,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con case Kind::BareCall: case Kind::BareCallCode: case Kind::BareDelegateCall: + case Kind::BareStaticCall: { MemberList::MemberMap members; if (m_kind == Kind::External) @@ -2911,6 +2915,7 @@ bool FunctionType::isBareCall() const case Kind::BareCall: case Kind::BareCallCode: case Kind::BareDelegateCall: + case Kind::BareStaticCall: case Kind::ECRecover: case Kind::SHA256: case Kind::RIPEMD160: @@ -3054,6 +3059,7 @@ bool FunctionType::padArguments() const case Kind::BareCall: case Kind::BareCallCode: case Kind::BareDelegateCall: + case Kind::BareStaticCall: case Kind::SHA256: case Kind::RIPEMD160: case Kind::KECCAK256: diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index d8e73ab9..0b1b5d6d 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -904,6 +904,7 @@ public: BareCall, ///< CALL without function hash BareCallCode, ///< CALLCODE without function hash BareDelegateCall, ///< DELEGATECALL without function hash + BareStaticCall, ///< STATICCALL without function hash Creation, ///< external call using CREATE Send, ///< CALL, but without data and gas Transfer, ///< CALL, but without data and throws on error @@ -935,7 +936,7 @@ public: ABIEncodeWithSelector, ABIEncodeWithSignature, ABIDecode, - GasLeft ///< gasleft() + GasLeft, ///< gasleft() }; virtual Category category() const override { return Category::Function; } @@ -1051,7 +1052,7 @@ public: /// @returns true iff the function type is equal to the given type, ignoring state mutability differences. bool equalExcludingStateMutability(FunctionType const& _other) const; - /// @returns true if the ABI is used for this call (only meaningful for external calls) + /// @returns true if the ABI is NOT used for this call (only meaningful for external calls) bool isBareCall() const; Kind const& kind() const { return m_kind; } StateMutability stateMutability() const { return m_stateMutability; } @@ -1090,6 +1091,7 @@ public: case FunctionType::Kind::BareCall: case FunctionType::Kind::BareCallCode: case FunctionType::Kind::BareDelegateCall: + case FunctionType::Kind::BareStaticCall: return true; default: return false; -- cgit From 455345871d286c24d393fbc9dea3d8a71f1a5b23 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 15 Aug 2018 17:11:43 +0200 Subject: More safeguards for (library) function types. --- libsolidity/ast/Types.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c9dca126..2fb5fba2 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2924,6 +2924,17 @@ string FunctionType::externalSignature() const { solAssert(m_declaration != nullptr, "External signature of function needs declaration"); solAssert(!m_declaration->name().empty(), "Fallback function has no signature."); + switch (kind()) + { + case Kind::Internal: + case Kind::External: + case Kind::CallCode: + case Kind::DelegateCall: + case Kind::Event: + break; + default: + solAssert(false, "Invalid function type for requesting external signature."); + } bool const inLibrary = dynamic_cast(*m_declaration->scope()).isLibrary(); FunctionTypePointer external = interfaceFunctionType(); -- cgit From 74c37935f0e0c028c007f306597c74a4834e53f7 Mon Sep 17 00:00:00 2001 From: liangdzou Date: Thu, 16 Aug 2018 13:42:46 +0800 Subject: fix a typo: declaratoion => declaration --- libsolidity/ast/AST.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libsolidity/ast') diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a376e55d..635ab024 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -397,7 +397,7 @@ SourceUnit const& Scopable::sourceUnit() const { ASTNode const* s = scope(); solAssert(s, ""); - // will not always be a declaratoion + // will not always be a declaration while (dynamic_cast(s) && dynamic_cast(s)->scope()) s = dynamic_cast(s)->scope(); return dynamic_cast(*s); -- cgit