aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/bugs.json8
-rw-r--r--docs/bugs_by_version.json14
-rw-r--r--libsolidity/analysis/TypeChecker.cpp10
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp203
-rw-r--r--test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol7
-rw-r--r--test/libsolidity/syntaxTests/events/event_array_v2.sol6
-rw-r--r--test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol7
-rw-r--r--test/libsolidity/syntaxTests/events/event_nested_array_v2.sol6
-rw-r--r--test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol8
-rw-r--r--test/libsolidity/syntaxTests/events/event_struct_v2.sol7
11 files changed, 275 insertions, 2 deletions
diff --git a/Changelog.md b/Changelog.md
index 177a071b..5fcf134b 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -108,6 +108,7 @@ Bugfixes:
* Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
* Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``.
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
+ * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values.
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
### 0.4.24 (2018-05-16)
diff --git a/docs/bugs.json b/docs/bugs.json
index 3f20077f..839ea128 100644
--- a/docs/bugs.json
+++ b/docs/bugs.json
@@ -1,5 +1,13 @@
[
{
+ "name": "EventStructWrongData",
+ "summary": "Using structs in events logged wrong data.",
+ "description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.",
+ "introduced": "0.4.17",
+ "fixed": "0.5.0",
+ "severity": "very low"
+ },
+ {
"name": "NestedArrayFunctionCallDecoder",
"summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.",
"description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.",
diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json
index b400121f..560b6fa9 100644
--- a/docs/bugs_by_version.json
+++ b/docs/bugs_by_version.json
@@ -412,6 +412,7 @@
},
"0.4.17": {
"bugs": [
+ "EventStructWrongData",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
],
@@ -419,12 +420,14 @@
},
"0.4.18": {
"bugs": [
+ "EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
"released": "2017-10-18"
},
"0.4.19": {
"bugs": [
+ "EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
"released": "2017-11-30"
@@ -445,28 +448,35 @@
},
"0.4.20": {
"bugs": [
+ "EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
"released": "2018-02-14"
},
"0.4.21": {
"bugs": [
+ "EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
"released": "2018-03-07"
},
"0.4.22": {
"bugs": [
+ "EventStructWrongData",
"OneOfTwoConstructorsSkipped"
],
"released": "2018-04-16"
},
"0.4.23": {
- "bugs": [],
+ "bugs": [
+ "EventStructWrongData"
+ ],
"released": "2018-04-19"
},
"0.4.24": {
- "bugs": [],
+ "bugs": [
+ "EventStructWrongData"
+ ],
"released": "2018-05-16"
},
"0.4.3": {
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 43e894e5..c737fe41 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -895,7 +895,17 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters())
{
if (var->isIndexed())
+ {
numIndexed++;
+ if (
+ _eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
+ dynamic_cast<ReferenceType const*>(type(*var).get())
+ )
+ m_errorReporter.typeError(
+ var->location(),
+ "Indexed reference types cannot yet be used with ABIEncoderV2."
+ );
+ }
if (!type(*var)->canLiveOutsideStorage())
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (!type(*var)->interfaceType(false))
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 8a334e5e..ce3c4324 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -3937,6 +3937,209 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
}
+BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ struct S { uint a; }
+ event E(S);
+ function createEvent(uint x) public {
+ emit E(S(x));
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(x));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
+}
+
+BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ struct S { uint a; }
+ event E(S);
+ S s;
+ function createEvent(uint x) public {
+ s.a = x;
+ emit E(s);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(x));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
+{
+ char const* sourceCode = R"(
+ contract C {
+ event E(uint[]);
+ function createEvent(uint x) public {
+ uint[] memory arr = new uint[](3);
+ arr[0] = x;
+ arr[1] = x + 1;
+ arr[2] = x + 2;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ event E(uint[]);
+ function createEvent(uint x) public {
+ uint[] memory arr = new uint[](3);
+ arr[0] = x;
+ arr[1] = x + 1;
+ arr[2] = x + 2;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ event E(uint[][]);
+ function createEvent(uint x) public {
+ uint[][] memory arr = new uint[][](2);
+ arr[0] = new uint[](2);
+ arr[1] = new uint[](2);
+ arr[0][0] = x;
+ arr[0][1] = x + 1;
+ arr[1][0] = x + 2;
+ arr[1][1] = x + 3;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
+{
+ char const* sourceCode = R"(
+ contract C {
+ event E(uint[]);
+ uint[] arr;
+ function createEvent(uint x) public {
+ arr.length = 3;
+ arr[0] = x;
+ arr[1] = x + 1;
+ arr[2] = x + 2;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_array_storage_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ event E(uint[]);
+ uint[] arr;
+ function createEvent(uint x) public {
+ arr.length = 3;
+ arr[0] = x;
+ arr[1] = x + 1;
+ arr[2] = x + 2;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
+}
+
+BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_storage_v2)
+{
+ char const* sourceCode = R"(
+ pragma experimental ABIEncoderV2;
+ contract C {
+ event E(uint[][]);
+ uint[][] arr;
+ function createEvent(uint x) public {
+ arr.length = 2;
+ arr[0].length = 2;
+ arr[1].length = 2;
+ arr[0][0] = x;
+ arr[0][1] = x + 1;
+ arr[1][0] = x + 2;
+ arr[1][1] = x + 3;
+ emit E(arr);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ u256 x(42);
+ callContractFunction("createEvent(uint256)", x);
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
+}
+
BOOST_AUTO_TEST_CASE(event_indexed_string)
{
char const* sourceCode = R"(
diff --git a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol
new file mode 100644
index 00000000..aaf6028a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol
@@ -0,0 +1,7 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ event E(uint[] indexed);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
+// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2.
diff --git a/test/libsolidity/syntaxTests/events/event_array_v2.sol b/test/libsolidity/syntaxTests/events/event_array_v2.sol
new file mode 100644
index 00000000..9ccd9fc9
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_array_v2.sol
@@ -0,0 +1,6 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ event E(uint[]);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol
new file mode 100644
index 00000000..ffae5b9c
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol
@@ -0,0 +1,7 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ event E(uint[][] indexed);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
+// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2.
diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_v2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_v2.sol
new file mode 100644
index 00000000..efc7439e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_nested_array_v2.sol
@@ -0,0 +1,6 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ event E(uint[][]);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol
new file mode 100644
index 00000000..a8e0837f
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol
@@ -0,0 +1,8 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ struct S { uint a ; }
+ event E(S indexed);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
+// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2.
diff --git a/test/libsolidity/syntaxTests/events/event_struct_v2.sol b/test/libsolidity/syntaxTests/events/event_struct_v2.sol
new file mode 100644
index 00000000..97ca61b6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/events/event_struct_v2.sol
@@ -0,0 +1,7 @@
+pragma experimental ABIEncoderV2;
+contract c {
+ struct S { uint a ; }
+ event E(S);
+}
+// ----
+// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.