Skip to content

Commit c164f80

Browse files
authored
Merge pull request #4820 from ethereum/disallow_indexed_ref_v2
Disallow indexed reference types in events when using ABIEncoderV2
2 parents e95901d + c00db3c commit c164f80

11 files changed

+275
-2
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ Bugfixes:
108108
* Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
109109
* Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``.
110110
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
111+
* Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values.
111112
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
112113

113114
### 0.4.24 (2018-05-16)

docs/bugs.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
[
2+
{
3+
"name": "EventStructWrongData",
4+
"summary": "Using structs in events logged wrong data.",
5+
"description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.",
6+
"introduced": "0.4.17",
7+
"fixed": "0.5.0",
8+
"severity": "very low"
9+
},
210
{
311
"name": "NestedArrayFunctionCallDecoder",
412
"summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.",

docs/bugs_by_version.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,19 +412,22 @@
412412
},
413413
"0.4.17": {
414414
"bugs": [
415+
"EventStructWrongData",
415416
"NestedArrayFunctionCallDecoder",
416417
"ZeroFunctionSelector"
417418
],
418419
"released": "2017-09-21"
419420
},
420421
"0.4.18": {
421422
"bugs": [
423+
"EventStructWrongData",
422424
"NestedArrayFunctionCallDecoder"
423425
],
424426
"released": "2017-10-18"
425427
},
426428
"0.4.19": {
427429
"bugs": [
430+
"EventStructWrongData",
428431
"NestedArrayFunctionCallDecoder"
429432
],
430433
"released": "2017-11-30"
@@ -445,28 +448,35 @@
445448
},
446449
"0.4.20": {
447450
"bugs": [
451+
"EventStructWrongData",
448452
"NestedArrayFunctionCallDecoder"
449453
],
450454
"released": "2018-02-14"
451455
},
452456
"0.4.21": {
453457
"bugs": [
458+
"EventStructWrongData",
454459
"NestedArrayFunctionCallDecoder"
455460
],
456461
"released": "2018-03-07"
457462
},
458463
"0.4.22": {
459464
"bugs": [
465+
"EventStructWrongData",
460466
"OneOfTwoConstructorsSkipped"
461467
],
462468
"released": "2018-04-16"
463469
},
464470
"0.4.23": {
465-
"bugs": [],
471+
"bugs": [
472+
"EventStructWrongData"
473+
],
466474
"released": "2018-04-19"
467475
},
468476
"0.4.24": {
469-
"bugs": [],
477+
"bugs": [
478+
"EventStructWrongData"
479+
],
470480
"released": "2018-05-16"
471481
},
472482
"0.4.3": {

libsolidity/analysis/TypeChecker.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,17 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
895895
for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters())
896896
{
897897
if (var->isIndexed())
898+
{
898899
numIndexed++;
900+
if (
901+
_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
902+
dynamic_cast<ReferenceType const*>(type(*var).get())
903+
)
904+
m_errorReporter.typeError(
905+
var->location(),
906+
"Indexed reference types cannot yet be used with ABIEncoderV2."
907+
);
908+
}
899909
if (!type(*var)->canLiveOutsideStorage())
900910
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
901911
if (!type(*var)->interfaceType(false))

test/libsolidity/SolidityEndToEndTest.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3937,6 +3937,209 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
39373937
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
39383938
}
39393939

3940+
BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
3941+
{
3942+
char const* sourceCode = R"(
3943+
pragma experimental ABIEncoderV2;
3944+
contract C {
3945+
struct S { uint a; }
3946+
event E(S);
3947+
function createEvent(uint x) public {
3948+
emit E(S(x));
3949+
}
3950+
}
3951+
)";
3952+
compileAndRun(sourceCode);
3953+
u256 x(42);
3954+
callContractFunction("createEvent(uint256)", x);
3955+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
3956+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
3957+
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
3958+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
3959+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
3960+
}
3961+
3962+
BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
3963+
{
3964+
char const* sourceCode = R"(
3965+
pragma experimental ABIEncoderV2;
3966+
contract C {
3967+
struct S { uint a; }
3968+
event E(S);
3969+
S s;
3970+
function createEvent(uint x) public {
3971+
s.a = x;
3972+
emit E(s);
3973+
}
3974+
}
3975+
)";
3976+
compileAndRun(sourceCode);
3977+
u256 x(42);
3978+
callContractFunction("createEvent(uint256)", x);
3979+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
3980+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
3981+
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
3982+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
3983+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
3984+
}
3985+
3986+
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
3987+
{
3988+
char const* sourceCode = R"(
3989+
contract C {
3990+
event E(uint[]);
3991+
function createEvent(uint x) public {
3992+
uint[] memory arr = new uint[](3);
3993+
arr[0] = x;
3994+
arr[1] = x + 1;
3995+
arr[2] = x + 2;
3996+
emit E(arr);
3997+
}
3998+
}
3999+
)";
4000+
compileAndRun(sourceCode);
4001+
u256 x(42);
4002+
callContractFunction("createEvent(uint256)", x);
4003+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4004+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4005+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
4006+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4007+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
4008+
}
4009+
4010+
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
4011+
{
4012+
char const* sourceCode = R"(
4013+
pragma experimental ABIEncoderV2;
4014+
contract C {
4015+
event E(uint[]);
4016+
function createEvent(uint x) public {
4017+
uint[] memory arr = new uint[](3);
4018+
arr[0] = x;
4019+
arr[1] = x + 1;
4020+
arr[2] = x + 2;
4021+
emit E(arr);
4022+
}
4023+
}
4024+
)";
4025+
compileAndRun(sourceCode);
4026+
u256 x(42);
4027+
callContractFunction("createEvent(uint256)", x);
4028+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4029+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4030+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
4031+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4032+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
4033+
}
4034+
4035+
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
4036+
{
4037+
char const* sourceCode = R"(
4038+
pragma experimental ABIEncoderV2;
4039+
contract C {
4040+
event E(uint[][]);
4041+
function createEvent(uint x) public {
4042+
uint[][] memory arr = new uint[][](2);
4043+
arr[0] = new uint[](2);
4044+
arr[1] = new uint[](2);
4045+
arr[0][0] = x;
4046+
arr[0][1] = x + 1;
4047+
arr[1][0] = x + 2;
4048+
arr[1][1] = x + 3;
4049+
emit E(arr);
4050+
}
4051+
}
4052+
)";
4053+
compileAndRun(sourceCode);
4054+
u256 x(42);
4055+
callContractFunction("createEvent(uint256)", x);
4056+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4057+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4058+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
4059+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4060+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
4061+
}
4062+
4063+
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
4064+
{
4065+
char const* sourceCode = R"(
4066+
contract C {
4067+
event E(uint[]);
4068+
uint[] arr;
4069+
function createEvent(uint x) public {
4070+
arr.length = 3;
4071+
arr[0] = x;
4072+
arr[1] = x + 1;
4073+
arr[2] = x + 2;
4074+
emit E(arr);
4075+
}
4076+
}
4077+
)";
4078+
compileAndRun(sourceCode);
4079+
u256 x(42);
4080+
callContractFunction("createEvent(uint256)", x);
4081+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4082+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4083+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
4084+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4085+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
4086+
}
4087+
4088+
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage_v2)
4089+
{
4090+
char const* sourceCode = R"(
4091+
pragma experimental ABIEncoderV2;
4092+
contract C {
4093+
event E(uint[]);
4094+
uint[] arr;
4095+
function createEvent(uint x) public {
4096+
arr.length = 3;
4097+
arr[0] = x;
4098+
arr[1] = x + 1;
4099+
arr[2] = x + 2;
4100+
emit E(arr);
4101+
}
4102+
}
4103+
)";
4104+
compileAndRun(sourceCode);
4105+
u256 x(42);
4106+
callContractFunction("createEvent(uint256)", x);
4107+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4108+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4109+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
4110+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4111+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
4112+
}
4113+
4114+
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_storage_v2)
4115+
{
4116+
char const* sourceCode = R"(
4117+
pragma experimental ABIEncoderV2;
4118+
contract C {
4119+
event E(uint[][]);
4120+
uint[][] arr;
4121+
function createEvent(uint x) public {
4122+
arr.length = 2;
4123+
arr[0].length = 2;
4124+
arr[1].length = 2;
4125+
arr[0][0] = x;
4126+
arr[0][1] = x + 1;
4127+
arr[1][0] = x + 2;
4128+
arr[1][1] = x + 3;
4129+
emit E(arr);
4130+
}
4131+
}
4132+
)";
4133+
compileAndRun(sourceCode);
4134+
u256 x(42);
4135+
callContractFunction("createEvent(uint256)", x);
4136+
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
4137+
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
4138+
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
4139+
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
4140+
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
4141+
}
4142+
39404143
BOOST_AUTO_TEST_CASE(event_indexed_string)
39414144
{
39424145
char const* sourceCode = R"(
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
event E(uint[] indexed);
4+
}
5+
// ----
6+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
7+
// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
event E(uint[]);
4+
}
5+
// ----
6+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
event E(uint[][] indexed);
4+
}
5+
// ----
6+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
7+
// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
event E(uint[][]);
4+
}
5+
// ----
6+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
struct S { uint a ; }
4+
event E(S indexed);
5+
}
6+
// ----
7+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
8+
// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pragma experimental ABIEncoderV2;
2+
contract c {
3+
struct S { uint a ; }
4+
event E(S);
5+
}
6+
// ----
7+
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.

0 commit comments

Comments
 (0)