From 5c59d56335f3777b9e4ad595b66787ed563b26f1 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 8 May 2018 14:26:01 +0200 Subject: Disallow conversions between bytesX and uintY of different size. --- Changelog.md | 1 + docs/types.rst | 9 +++++++++ libsolidity/ast/Types.cpp | 9 ++++++--- test/compilationTests/milestonetracker/RLP.sol | 2 +- test/libsolidity/SolidityNameAndTypeResolution.cpp | 13 ------------- .../syntaxTests/types/bytes1_to_uint256.sol | 7 +++++++ .../syntaxTests/types/bytes32_to_uint32.sol | 7 +++++++ .../syntaxTests/types/bytes_to_contract.sol | 4 ++-- .../syntaxTests/types/bytes_to_uint_same_size.sol | 20 ++++++++++++++++++++ .../syntaxTests/types/index_access_for_bytes.sol | 6 ++++++ .../syntaxTests/types/uint256_to_bytes1.sol | 7 +++++++ .../syntaxTests/types/uint32_to_bytes32.sol | 7 +++++++ 12 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol create mode 100644 test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol create mode 100644 test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol create mode 100644 test/libsolidity/syntaxTests/types/index_access_for_bytes.sol create mode 100644 test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol create mode 100644 test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol diff --git a/Changelog.md b/Changelog.md index e047f336..98bb5f0a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.5.0 (unreleased) Breaking Changes: + * Disallow conversions between bytesX and uintY of different size. * Type Checker: Disallow arithmetic operations for Boolean variables. Features: diff --git a/docs/types.rst b/docs/types.rst index 5c20dc67..63cdbe05 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -975,6 +975,15 @@ cut off:: uint32 a = 0x12345678; uint16 b = uint16(a); // b will be 0x5678 now +Since 0.5.0 explicit conversions between integers and fixed-size byte arrays +are only allowed, if both have the same size. To convert between integers and +fixed-size byte arrays of different size, they first have to be explicitly +converted to a matching size. This makes alignment and padding explicit:: + + uint16 x = 0xffff; + bytes32(uint256(x)); // pad on the left + bytes32(bytes2(x)); // pad on the right + .. index:: ! type;deduction, ! var .. _type-deduction: diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 066868c9..000b1063 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -476,7 +476,7 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const return _convertTo.category() == category() || _convertTo.category() == Category::Contract || _convertTo.category() == Category::Enum || - _convertTo.category() == Category::FixedBytes || + (_convertTo.category() == Category::FixedBytes && numBits() == dynamic_cast(_convertTo).numBytes() * 8) || _convertTo.category() == Category::FixedPoint; } @@ -884,7 +884,10 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const { TypePointer mobType = mobileType(); - return mobType && mobType->isExplicitlyConvertibleTo(_convertTo); + return + (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) || + (!isFractional() && _convertTo.category() == Category::FixedBytes) + ; } TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const @@ -1281,7 +1284,7 @@ bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - return _convertTo.category() == Category::Integer || + return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast(_convertTo).numBits()) || _convertTo.category() == Category::FixedPoint || _convertTo.category() == category(); } diff --git a/test/compilationTests/milestonetracker/RLP.sol b/test/compilationTests/milestonetracker/RLP.sol index 5bb27bb2..1b8cd1cb 100644 --- a/test/compilationTests/milestonetracker/RLP.sol +++ b/test/compilationTests/milestonetracker/RLP.sol @@ -263,7 +263,7 @@ library RLP { var (rStartPos, len) = _decode(self); if (len != 1) throw; - uint temp; + uint8 temp; assembly { temp := byte(0, mload(rStartPos)) } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 5af67659..efc3f24f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -3859,19 +3859,6 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(index_access_for_bytes) -{ - char const* text = R"( - contract C { - bytes20 x; - function f(bytes16 b) public { - b[uint(x[2])]; - } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier) { char const* text = R"( diff --git a/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol new file mode 100644 index 00000000..58828a62 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint256) { + return uint256(bytes1('')); + } +} +// ---- +// TypeError: (76-95): Explicit type conversion not allowed from "bytes1" to "uint256". diff --git a/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol new file mode 100644 index 00000000..77e813ab --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint32) { + return uint32(bytes32('')); + } +} +// ---- +// TypeError: (75-94): Explicit type conversion not allowed from "bytes32" to "uint32". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol index 2a3219ec..820dbf9b 100644 --- a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol +++ b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol @@ -1,7 +1,7 @@ contract C { function f() public pure { - C(bytes20(0x1234)); + C(bytes20(uint160(0x1234))); } } // ---- -// TypeError: (64-82): Explicit type conversion not allowed from "bytes20" to "contract C". +// TypeError: (64-91): Explicit type conversion not allowed from "bytes20" to "contract C". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol new file mode 100644 index 00000000..2963cfd2 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol @@ -0,0 +1,20 @@ +contract C { + function f() public pure returns (uint256) { + return uint256(bytes32(uint256(0))); + } + function g() public pure returns (uint128) { + return uint128(bytes16(uint128(0))); + } + function h() public pure returns (uint64) { + return uint64(bytes8(uint64(0))); + } + function i() public pure returns (uint32) { + return uint32(bytes4(uint32(0))); + } + function j() public pure returns (uint16) { + return uint16(bytes2(uint16(0))); + } + function k() public pure returns (uint8) { + return uint8(bytes1(uint8(0))); + } +} diff --git a/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol new file mode 100644 index 00000000..f31b4cc0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol @@ -0,0 +1,6 @@ +contract C { + bytes20 x; + function f(bytes16 b) public view { + b[uint8(x[2])]; + } +} diff --git a/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol new file mode 100644 index 00000000..f70c89ed --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes1) { + return bytes1(uint256(0)); + } +} +// ---- +// TypeError: (75-93): Explicit type conversion not allowed from "uint256" to "bytes1". diff --git a/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol new file mode 100644 index 00000000..4153c5c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes32) { + return bytes32(uint32(0)); + } +} +// ---- +// TypeError: (76-94): Explicit type conversion not allowed from "uint32" to "bytes32". -- cgit