aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/contracts.rst2
-rw-r--r--docs/types.rst11
-rw-r--r--libsolidity/ast/Types.cpp9
-rw-r--r--test/compilationTests/milestonetracker/RLP.sol2
-rw-r--r--test/libsolidity/ABIDecoderTests.cpp2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp42
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp13
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp2
-rw-r--r--test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol7
-rw-r--r--test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol7
-rw-r--r--test/libsolidity/syntaxTests/types/bytes_to_contract.sol4
-rw-r--r--test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol20
-rw-r--r--test/libsolidity/syntaxTests/types/index_access_for_bytes.sol6
-rw-r--r--test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol7
-rw-r--r--test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol7
16 files changed, 98 insertions, 44 deletions
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/contracts.rst b/docs/contracts.rst
index b73fe2ca..00ef3fc6 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -802,7 +802,7 @@ as topics. The event call above can be performed in the same way as
log3(
bytes32(msg.value),
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
- bytes32(msg.sender),
+ bytes32(uint256(msg.sender)),
_id
);
}
diff --git a/docs/types.rst b/docs/types.rst
index 5c20dc67..3f799c32 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -762,7 +762,7 @@ Members
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
- b[i] = byte(i);
+ b[i] = byte(uint8(i));
return b;
}
}
@@ -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<FixedBytesType const&>(_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<IntegerType const&>(_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/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp
index beb7b5af..b3ebb7a5 100644
--- a/test/libsolidity/ABIDecoderTests.cpp
+++ b/test/libsolidity/ABIDecoderTests.cpp
@@ -579,7 +579,7 @@ BOOST_AUTO_TEST_CASE(struct_simple)
a = s.a;
b = s.b;
c = s.c;
- d = uint(s.d);
+ d = uint16(s.d);
}
}
)";
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 1efcfde0..36840568 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -1667,7 +1667,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size)
char const* sourceCode = R"(
contract Test {
function bytesToUint(bytes4 s) returns (uint16 h) {
- return uint16(s);
+ return uint16(uint32(s));
}
}
)";
@@ -1683,7 +1683,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size)
char const* sourceCode = R"(
contract Test {
function bytesToUint(bytes4 s) returns (uint64 h) {
- return uint64(s);
+ return uint64(uint32(s));
}
}
)";
@@ -1730,7 +1730,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size)
char const* sourceCode = R"(
contract Test {
function uintToBytes(uint32 h) returns (bytes2 s) {
- return bytes2(h);
+ return bytes2(uint16(h));
}
}
)";
@@ -1746,7 +1746,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size)
char const* sourceCode = R"(
contract Test {
function UintToBytes(uint16 h) returns (bytes8 s) {
- return bytes8(h);
+ return bytes8(uint64(h));
}
}
)";
@@ -3128,7 +3128,7 @@ BOOST_AUTO_TEST_CASE(event)
function deposit(bytes32 _id, bool _manually) payable {
if (_manually) {
bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f;
- log3(bytes32(msg.value), s, bytes32(msg.sender), _id);
+ log3(bytes32(msg.value), s, bytes32(uint256(msg.sender)), _id);
} else {
Deposit(msg.sender, _id, msg.value);
}
@@ -3525,7 +3525,7 @@ BOOST_AUTO_TEST_CASE(event_indexed_string)
event E(string indexed r, uint[4] indexed t);
function deposit() {
bytes(x).length = 90;
- for (uint i = 0; i < 90; i++)
+ for (uint8 i = 0; i < 90; i++)
bytes(x)[i] = byte(i);
y[0] = 4;
y[1] = 5;
@@ -4753,7 +4753,7 @@ BOOST_AUTO_TEST_CASE(array_copy_different_packing)
function test() returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) {
data1.length = 9;
for (uint i = 0; i < data1.length; ++i)
- data1[i] = bytes8(i);
+ data1[i] = bytes8(uint64(i));
data2 = data1;
a = data2[1];
b = data2[2];
@@ -4781,7 +4781,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple)
bytes17[10] data2; // 1 per slot, no offset counter
function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) {
for (uint i = 0; i < data1.length; ++i)
- data1[i] = bytes8(i);
+ data1[i] = bytes8(uint64(i));
data2[8] = data2[9] = 2;
data2 = data1;
a = data2[1];
@@ -4813,14 +4813,14 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover)
uint i;
for (i = 0; i < data2.length; ++i)
data2[i] = 0xffff;
- check = uint(data2[31]) * 0x10000 | uint(data2[14]);
+ check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14]));
for (i = 0; i < data1.length; ++i)
data1[i] = byte(uint8(1 + i));
data2 = data1;
for (i = 0; i < 16; ++i)
- res1 |= uint(data2[i]) * 0x10000**i;
+ res1 |= uint(uint16(data2[i])) * 0x10000**i;
for (i = 0; i < 16; ++i)
- res2 |= uint(data2[16 + i]) * 0x10000**i;
+ res2 |= uint(uint16(data2[16 + i])) * 0x10000**i;
}
}
)";
@@ -4846,7 +4846,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2)
data1[2] = 3;
data1[3] = 4;
for (uint i = 0; i < data2.length; ++i)
- data2[i] = bytes10(0xffff00 | (1 + i));
+ data2[i] = bytes10(uint80(0xffff00 | (1 + i)));
data2 = data1;
r1 = data2[3];
r2 = data2[4];
@@ -5060,7 +5060,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition)
contract c {
bytes data;
function test() returns (uint) {
- for (uint i = 1; i < 40; i++)
+ for (uint8 i = 1; i < 40; i++)
{
data.push(byte(i));
if (data.length != i) return 0x1000 + i;
@@ -5106,11 +5106,11 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
contract c {
bytes data;
function direct(bytes arg, uint index) external returns (uint) {
- return uint(arg[index]);
+ return uint(uint8(arg[index]));
}
function storageCopyRead(bytes arg, uint index) external returns (uint) {
data = arg;
- return uint(data[index]);
+ return uint(uint8(data[index]));
}
function storageWrite() external returns (uint) {
data.length = 35;
@@ -5121,7 +5121,7 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
data[31] |= 8;
data[30] = 1;
data[32] = 3;
- return uint(data[30]) * 0x100 | uint(data[31]) * 0x10 | uint(data[32]);
+ return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32]));
}
}
)";
@@ -5144,7 +5144,7 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element)
function test1() external returns (bool) {
data.length = 100;
for (uint i = 0; i < data.length; i++)
- data[i] = byte(i);
+ data[i] = byte(uint8(i));
delete data[94];
delete data[96];
delete data[98];
@@ -7498,7 +7498,7 @@ BOOST_AUTO_TEST_CASE(short_strings)
if (data1[0] != "1") return 10;
if (data1[4] != "4") return 11;
for (uint i = 0; i < data1.length; i ++)
- data1[i] = byte(i * 3);
+ data1[i] = byte(uint8(i * 3));
if (data1[4] != 4 * 3) return 12;
if (data1[67] != 67 * 3) return 13;
// change length: long -> short
@@ -8314,7 +8314,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access)
function g(bytes32 x) returns (uint) {
data = [x[0], x[1], x[2]];
data[0] = "12345";
- return uint(data[0][4]);
+ return uint(uint8(data[0][4]));
}
}
)";
@@ -8372,7 +8372,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_memory_access)
function test() returns (bytes) {
bytes memory x = new bytes(5);
for (uint i = 0; i < x.length; ++i)
- x[i] = byte(i + 1);
+ x[i] = byte(uint8(i + 1));
assembly { mstore(add(x, 32), "12345678901234567890123456789012") }
return x;
}
@@ -8892,7 +8892,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types)
function f(bytes2 a, uint16 x) returns (uint) {
if (a != "ab") return 1;
if (x != 0x0102) return 2;
- if (bytes3(x) != 0x0102) return 3;
+ if (bytes3(uint24(x)) != 0x0102) return 3;
return 0;
}
}
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/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index 5326feaf..184b7a8d 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(array_copy)
data1[i] = msg.data[i];
data2 = data1;
l = data2.length;
- y = uint(data2[x]);
+ y = uint(uint40(data2[x]));
}
}
)";
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".