From d2445dfdced2d4e1fccdd873963e02663c0116c1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 23 Jun 2017 18:36:56 +0200 Subject: Tests for comparison of non-comparable types. --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a6027812..0c56e585 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -554,6 +554,40 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(comparison_of_function_types) +{ + char const* text = R"( + contract C { + function f() returns (bool ret) { + return this.f < this.f; + } + } + )"; + CHECK_ERROR(text, TypeError, "Operator < not compatible"); + text = R"( + contract C { + function f() returns (bool ret) { + return f < f; + } + } + )"; + CHECK_SUCCESS(text); +} + +BOOST_AUTO_TEST_CASE(comparison_of_mapping_types) +{ + char const* text = R"( + contract C { + mapping(uint => uint) x; + function f() returns (bool ret) { + var y = x; + return x == y; + } + } + )"; + CHECK_ERROR(text, TypeError, "Operator == not compatible"); +} + BOOST_AUTO_TEST_CASE(function_no_implementation) { ASTPointer sourceUnit; -- cgit v1.2.3 From f47e6e90fb55066ff602a1448fc2d3f650449559 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 23 Jun 2017 18:37:15 +0200 Subject: Disallow comparisons between some types. --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 10 ++++++++++ libsolidity/ast/Types.h | 9 ++++----- libsolidity/codegen/ExpressionCompiler.cpp | 1 + 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index cfedf1fc..8eaa8271 100644 --- a/Changelog.md +++ b/Changelog.md @@ -19,6 +19,7 @@ Bugfixes: * Type Checker: Fix address literals not being treated as compile-time constants. * Type Checker: Disallow invoking the same modifier multiple times. * Type Checker: Make UTF8-validation a bit more sloppy to include more valid sequences. + * Type Checker: Disallow comparisons between mapping and non-internal function types. * Type Checker: Do not treat strings that look like addresses as addresses. * Fixed crash concerning non-callable types. * Unused variable warnings no longer issued for variables used inside inline assembly. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index bd3346f9..0234f842 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2248,6 +2248,16 @@ TypePointer FunctionType::unaryOperatorResult(Token::Value _operator) const return TypePointer(); } +TypePointer FunctionType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const +{ + if (_other->category() != category() || !Token::isCompareOp(_operator)) + return TypePointer(); + FunctionType const& other = dynamic_cast(*_other); + if (kind() == Kind::Internal && other.kind() == Kind::Internal && sizeOnStack() == 1 && other.sizeOnStack() == 1) + return commonType(shared_from_this(), _other); + return TypePointer(); +} + string FunctionType::canonicalName(bool) const { solAssert(m_kind == Kind::External, ""); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index c4ffc44c..f7a73ab5 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -933,6 +933,7 @@ public: virtual bool operator==(Type const& _other) 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; virtual std::string canonicalName(bool /*_addDataLocation*/) const override; virtual std::string toString(bool _short) const override; virtual unsigned calldataEncodedSize(bool _padded) const override; @@ -1038,6 +1039,7 @@ public: virtual std::string toString(bool _short) const override; virtual std::string canonicalName(bool _addDataLocation) const override; virtual bool canLiveOutsideStorage() const override { return false; } + virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } virtual TypePointer encodingType() const override { return std::make_shared(256); @@ -1116,11 +1118,7 @@ public: explicit ModuleType(SourceUnit const& _source): m_sourceUnit(_source) {} - virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override - { - return TypePointer(); - } - + virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } virtual std::string identifier() const override; virtual bool operator==(Type const& _other) const override; virtual bool canBeStored() const override { return false; } @@ -1178,6 +1176,7 @@ public: virtual std::string identifier() const override { return "t_inaccessible"; } virtual bool isImplicitlyConvertibleTo(Type const&) const override { return false; } virtual bool isExplicitlyConvertibleTo(Type const&) const override { return false; } + virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } virtual unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; } virtual bool canBeStored() const override { return false; } virtual bool canLiveOutsideStorage() const override { return false; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index a7cfe4dc..a65549fd 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1366,6 +1366,7 @@ void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryO void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type const& _type) { + solAssert(_type.sizeOnStack() == 1, "Comparison of multi-slot types."); if (_operator == Token::Equal || _operator == Token::NotEqual) { if (FunctionType const* funType = dynamic_cast(&_type)) -- cgit v1.2.3 From 4407a13c1730bf9ed4bcaf00c3f72640f6ddb2a7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 26 Jun 2017 16:30:13 +0200 Subject: Only allow equality checks for internal function types. --- libsolidity/ast/Types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0234f842..7dc6c4a6 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2250,7 +2250,7 @@ TypePointer FunctionType::unaryOperatorResult(Token::Value _operator) const TypePointer FunctionType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { - if (_other->category() != category() || !Token::isCompareOp(_operator)) + if (_other->category() != category() || !(_operator == Token::Equal || _operator == Token::NotEqual)) return TypePointer(); FunctionType const& other = dynamic_cast(*_other); if (kind() == Kind::Internal && other.kind() == Kind::Internal && sizeOnStack() == 1 && other.sizeOnStack() == 1) -- cgit v1.2.3 From 6b05bbbbb42dafdbf38661fd9c2c3c3e88a425a2 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 26 Jun 2017 22:01:35 +0100 Subject: Update tests for function type comparison --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 0c56e585..eb1cf0dc 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -571,6 +571,17 @@ BOOST_AUTO_TEST_CASE(comparison_of_function_types) } } )"; + CHECK_ERROR(text, TypeError, "Operator < not compatible"); + text = R"( + contract C { + function f() returns (bool ret) { + return f == f; + } + function g() returns (bool ret) { + return f != f; + } + } + )"; CHECK_SUCCESS(text); } -- cgit v1.2.3