From 507cdf6de20b5c9bc9a0a8de311e9018af552865 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 16:55:53 +0200 Subject: Set version. --- CMakeLists.txt | 2 +- Changelog.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c05208f..f30872af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.24") +set(PROJECT_VERSION "0.4.25") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) diff --git a/Changelog.md b/Changelog.md index 6a408ae8..0ad1b863 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,6 @@ +### 0.4.25 (unreleased) + + ### 0.4.24 (2018-05-16) Language Features: -- cgit v1.2.3 From c577e043a4d54ac740aab770a6af38d74a7a427d Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 1 Aug 2018 19:01:50 +0200 Subject: Disallow structs in events without ABIEncoderV2 --- Changelog.md | 2 ++ libsolidity/analysis/TypeChecker.cpp | 10 ++++++++++ test/libsolidity/SolidityABIJSON.cpp | 1 + test/libsolidity/syntaxTests/emit/emit_empty.sol | 7 +++++++ test/libsolidity/syntaxTests/emit/emit_non_event.sol | 10 ++++++++++ test/libsolidity/syntaxTests/emit_non_event.sol | 10 ---------- test/libsolidity/syntaxTests/events/event_nested_array.sol | 5 +++++ test/libsolidity/syntaxTests/events/event_nested_array_2.sol | 4 ++++ .../syntaxTests/events/event_nested_array_in_struct.sol | 6 ++++++ test/libsolidity/syntaxTests/events/event_struct.sol | 6 ++++++ test/libsolidity/syntaxTests/events/event_struct_indexed.sol | 6 ++++++ 11 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 test/libsolidity/syntaxTests/emit/emit_empty.sol create mode 100644 test/libsolidity/syntaxTests/emit/emit_non_event.sol delete mode 100644 test/libsolidity/syntaxTests/emit_non_event.sol create mode 100644 test/libsolidity/syntaxTests/events/event_nested_array.sol create mode 100644 test/libsolidity/syntaxTests/events/event_nested_array_2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol create mode 100644 test/libsolidity/syntaxTests/events/event_struct.sol create mode 100644 test/libsolidity/syntaxTests/events/event_struct_indexed.sol diff --git a/Changelog.md b/Changelog.md index 0ad1b863..26f7d5e2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,7 @@ ### 0.4.25 (unreleased) +Bugfixes: + * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. ### 0.4.24 (2018-05-16) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 30302908..f6980872 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -864,6 +864,7 @@ void TypeChecker::visitManually( bool TypeChecker::visit(EventDefinition const& _eventDef) { + solAssert(_eventDef.visibility() > Declaration::Visibility::Internal, ""); unsigned numIndexed = 0; for (ASTPointer const& var: _eventDef.parameters()) { @@ -873,6 +874,15 @@ bool TypeChecker::visit(EventDefinition const& _eventDef) m_errorReporter.typeError(var->location(), "Type is required to live outside storage."); if (!type(*var)->interfaceType(false)) m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type."); + if ( + !_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && + !typeSupportedByOldABIEncoder(*type(*var)) + ) + m_errorReporter.typeError( + var->location(), + "This type is only supported in the new experimental ABI encoder. " + "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." + ); } if (_eventDef.isAnonymous() && numIndexed > 4) m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event."); diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 107abc26..3475b018 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -1036,6 +1036,7 @@ BOOST_AUTO_TEST_CASE(return_structs_with_contracts) BOOST_AUTO_TEST_CASE(event_structs) { char const* text = R"( + pragma experimental ABIEncoderV2; contract C { struct S { uint a; T[] sub; bytes b; } struct T { uint[2] x; } diff --git a/test/libsolidity/syntaxTests/emit/emit_empty.sol b/test/libsolidity/syntaxTests/emit/emit_empty.sol new file mode 100644 index 00000000..819d88fe --- /dev/null +++ b/test/libsolidity/syntaxTests/emit/emit_empty.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + emit; + } +} +// ---- +// ParserError: (45-46): Expected event name or path. diff --git a/test/libsolidity/syntaxTests/emit/emit_non_event.sol b/test/libsolidity/syntaxTests/emit/emit_non_event.sol new file mode 100644 index 00000000..1df6990d --- /dev/null +++ b/test/libsolidity/syntaxTests/emit/emit_non_event.sol @@ -0,0 +1,10 @@ +contract C { + uint256 Test; + + function f() { + emit Test(); + } +} +// ---- +// TypeError: (56-62): Type is not callable +// TypeError: (56-60): Expression has to be an event invocation. diff --git a/test/libsolidity/syntaxTests/emit_non_event.sol b/test/libsolidity/syntaxTests/emit_non_event.sol deleted file mode 100644 index 1df6990d..00000000 --- a/test/libsolidity/syntaxTests/emit_non_event.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - uint256 Test; - - function f() { - emit Test(); - } -} -// ---- -// TypeError: (56-62): Type is not callable -// TypeError: (56-60): Expression has to be an event invocation. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array.sol b/test/libsolidity/syntaxTests/events/event_nested_array.sol new file mode 100644 index 00000000..70af63b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array.sol @@ -0,0 +1,5 @@ +contract c { + event E(uint[][]); +} +// ---- +// TypeError: (25-33): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_2.sol new file mode 100644 index 00000000..5825650e --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array_2.sol @@ -0,0 +1,4 @@ +contract c { + event E(uint[2][]); +} +// ---- diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol new file mode 100644 index 00000000..fd59e962 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint x; uint[][] arr; } + event E(S); +} +// ---- +// TypeError: (61-62): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct.sol b/test/libsolidity/syntaxTests/events/event_struct.sol new file mode 100644 index 00000000..c955dc5e --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_struct.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint a ; } + event E(S); +} +// ---- +// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol new file mode 100644 index 00000000..69ee5017 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint a ; } + event E(S indexed); +} +// ---- +// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. -- cgit v1.2.3 From 768ea5b0bee99aee6d74600ec37b2cdea906c77f Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 15 Aug 2018 12:30:29 +0200 Subject: Disallow indexed reference types in events when using ABIEncoderV2 --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 10 ++++++++++ test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol | 7 +++++++ test/libsolidity/syntaxTests/events/event_array_v2.sol | 6 ++++++ .../syntaxTests/events/event_nested_array_indexed_v2.sol | 7 +++++++ test/libsolidity/syntaxTests/events/event_nested_array_v2.sol | 6 ++++++ .../libsolidity/syntaxTests/events/event_struct_indexed_v2.sol | 8 ++++++++ test/libsolidity/syntaxTests/events/event_struct_v2.sol | 7 +++++++ 8 files changed, 52 insertions(+) create mode 100644 test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_array_v2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_nested_array_v2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol create mode 100644 test/libsolidity/syntaxTests/events/event_struct_v2.sol diff --git a/Changelog.md b/Changelog.md index 26f7d5e2..6397b23b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.25 (unreleased) Bugfixes: + * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. ### 0.4.24 (2018-05-16) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f6980872..f786a83d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -869,7 +869,17 @@ bool TypeChecker::visit(EventDefinition const& _eventDef) for (ASTPointer const& var: _eventDef.parameters()) { if (var->isIndexed()) + { numIndexed++; + if ( + _eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) + && dynamic_cast(type(*var).get()) + ) + m_errorReporter.typeError( + var->location(), + "Reference types cannot be indexed." + ); + } 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/syntaxTests/events/event_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol new file mode 100644 index 00000000..6b126db4 --- /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): Reference types cannot be indexed. 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..5c556125 --- /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): Reference types cannot be indexed. 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..8d2d4f8c --- /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): Reference types cannot be indexed. 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. -- cgit v1.2.3 From bc6366fd5231b1542e50acb9519535903134a44a Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 15 Aug 2018 16:54:13 +0200 Subject: Add end to end tests --- test/libsolidity/SolidityEndToEndTest.cpp | 203 ++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 1efcfde0..a4b59761 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -3516,6 +3516,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"( -- cgit v1.2.3 From 13c8bb1c8920b6ea507688e24adb68e3bf0aed9f Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 15 Aug 2018 16:58:41 +0200 Subject: Review suggestions --- libsolidity/analysis/TypeChecker.cpp | 6 +++--- test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol | 2 +- .../syntaxTests/events/event_nested_array_indexed_v2.sol | 2 +- test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f786a83d..2062458e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -872,12 +872,12 @@ bool TypeChecker::visit(EventDefinition const& _eventDef) { numIndexed++; if ( - _eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) - && dynamic_cast(type(*var).get()) + _eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && + dynamic_cast(type(*var).get()) ) m_errorReporter.typeError( var->location(), - "Reference types cannot be indexed." + "Indexed reference types cannot yet be used with ABIEncoderV2." ); } if (!type(*var)->canLiveOutsideStorage()) diff --git a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol index 6b126db4..aaf6028a 100644 --- a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-65): Reference types cannot be indexed. +// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol index 5c556125..ffae5b9c 100644 --- a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-67): Reference types cannot be indexed. +// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol index 8d2d4f8c..a8e0837f 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol @@ -5,4 +5,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (85-86): Reference types cannot be indexed. +// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2. -- cgit v1.2.3 From 409b20f204df74b24d77d9d88ea0fc9436c58d61 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 15 Aug 2018 17:10:02 +0200 Subject: Bug list entry --- docs/bugs.json | 8 ++++++++ docs/bugs_by_version.json | 26 ++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/bugs.json b/docs/bugs.json index b464be18..8eae2af3 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,12 @@ [ + { + "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": "OneOfTwoConstructorsSkipped", "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2fe1d226..00531b9e 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -389,16 +389,21 @@ }, "0.4.17": { "bugs": [ + "EventStructWrongData", "ZeroFunctionSelector" ], "released": "2017-09-21" }, "0.4.18": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "released": "2017-10-18" }, "0.4.19": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "released": "2017-11-30" }, "0.4.2": { @@ -415,25 +420,34 @@ "released": "2016-09-17" }, "0.4.20": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "released": "2018-02-14" }, "0.4.21": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "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": { -- cgit v1.2.3 From 99022216cd19ecb777bf20c4bfff6fd12395c12e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 16:59:53 +0200 Subject: Change "fixed" date. --- docs/bugs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bugs.json b/docs/bugs.json index 8eae2af3..423c314d 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -4,7 +4,7 @@ "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", + "fixed": "0.4.25", "severity": "very low" }, { -- cgit v1.2.3 From f531dd9fa0cfad50fef4e17c4c734e91187debfd Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Tue, 4 Sep 2018 12:09:37 +0200 Subject: Use wildcards for MSVC version in scripts/release.bat. --- scripts/release.bat | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/release.bat b/scripts/release.bat index be95b35e..b15b49b7 100644 --- a/scripts/release.bat +++ b/scripts/release.bat @@ -32,12 +32,9 @@ set VERSION=%2 IF "%VERSION%"=="2015" ( set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT\msvc*.dll" ) ELSE ( - - IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\" ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\msvc*.dll" - ) ELSE ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\14.13.26020\x86\Microsoft.VC141.CRT\msvc*.dll" - ) + set "DLLS=MSVC_DLLS_NOT_FOUND" + FOR /d %%d IN ("C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\*" + "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\*") DO set "DLLS=%%d\x86\Microsoft.VC141.CRT\msvc*.dll" ) 7z a solidity-windows.zip ^ -- cgit v1.2.3 From 65a439b0fbbd3723f9b6a456cbb9927b3ab5d121 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 5 Sep 2018 22:07:13 +0200 Subject: Refactor handling of whitespace. --- libsolidity/parsing/Scanner.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp index 6541f6c2..64acd411 100644 --- a/libsolidity/parsing/Scanner.cpp +++ b/libsolidity/parsing/Scanner.cpp @@ -435,11 +435,6 @@ void Scanner::scanToken() m_nextToken.location.start = sourcePos(); switch (m_char) { - case '\n': - case ' ': - case '\t': - token = selectToken(Token::Whitespace); - break; case '"': case '\'': token = scanString(); -- cgit v1.2.3 From c0d9b492a23537e99495ff84a4a24f55ebd9ebc7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 11:05:35 +0200 Subject: This fixes several bugs with regards to line breaks and comments: - any unicode line break (line feed, vertical tab, form feed, carriage return, NEL, LS and PS) is considered to terminate a single-line comment. The line break itself is considered to be the next token after the comment, leading to a parser error if it is not an ascii character (i.e. for NEL, LS and PS). - unterminated multiline comments are considered illegal tokens - '/** /' is considered an unterminated multiline comment (previously, whitespace was allowed before the last '/' --- libsolidity/parsing/Scanner.cpp | 79 ++++++++++++++++++++++++------------ libsolidity/parsing/Scanner.h | 7 +++- test/libsolidity/SolidityScanner.cpp | 8 ++++ 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp index 64acd411..dbe1f389 100644 --- a/libsolidity/parsing/Scanner.cpp +++ b/libsolidity/parsing/Scanner.cpp @@ -243,22 +243,17 @@ bool Scanner::skipWhitespace() return sourcePos() != startPosition; } -bool Scanner::skipWhitespaceExceptLF() +void Scanner::skipWhitespaceExceptUnicodeLinebreak() { - int const startPosition = sourcePos(); - while (isWhiteSpace(m_char) && !isLineTerminator(m_char)) + while (isWhiteSpace(m_char) && !isUnicodeLinebreak()) advance(); - // Return whether or not we skipped any characters. - return sourcePos() != startPosition; } Token::Value Scanner::skipSingleLineComment() { - // The line terminator at the end of the line is not considered - // to be part of the single-line comment; it is recognized - // separately by the lexical grammar and becomes part of the - // stream of input elements for the syntactic grammar - while (!isLineTerminator(m_char)) + // Line terminator is not part of the comment. If it is a + // non-ascii line terminator, it will result in a parser error. + while (!isUnicodeLinebreak()) if (!advance()) break; return Token::Whitespace; @@ -268,7 +263,9 @@ Token::Value Scanner::scanSingleLineDocComment() { LiteralScope literal(this, LITERAL_TYPE_COMMENT); advance(); //consume the last '/' at /// - skipWhitespaceExceptLF(); + + skipWhitespaceExceptUnicodeLinebreak(); + while (!isSourcePastEndOfInput()) { if (isLineTerminator(m_char)) @@ -287,6 +284,10 @@ Token::Value Scanner::scanSingleLineDocComment() break; // next line is not a documentation comment, we are done } + else if (isUnicodeLinebreak()) + // Any line terminator that is not '\n' is considered to end the + // comment. + break; addCommentLiteralChar(m_char); advance(); } @@ -321,6 +322,9 @@ Token::Value Scanner::scanMultiLineDocComment() bool endFound = false; bool charsAdded = false; + while (isWhiteSpace(m_char) && !isLineTerminator(m_char)) + advance(); + while (!isSourcePastEndOfInput()) { //handle newlines in multline comments @@ -372,7 +376,7 @@ Token::Value Scanner::scanSlash() if (m_char == '/') { if (!advance()) /* double slash comment directly before EOS */ - return Token::Whitespace; + return Token::Whitespace; else if (m_char == '/') { // doxygen style /// comment @@ -390,24 +394,27 @@ Token::Value Scanner::scanSlash() { // doxygen style /** natspec comment if (!advance()) /* slash star comment before EOS */ - return Token::Whitespace; + return Token::Illegal; else if (m_char == '*') { advance(); //consume the last '*' at /** - skipWhitespaceExceptLF(); - // special case of a closed normal multiline comment - if (!m_source.isPastEndOfInput() && m_source.get(0) == '/') - advance(); //skip the closing slash - else // we actually have a multiline documentation comment + // "/**/" + if (m_char == '/') { - Token::Value comment; - m_nextSkippedComment.location.start = firstSlashPosition; - comment = scanMultiLineDocComment(); - m_nextSkippedComment.location.end = sourcePos(); - m_nextSkippedComment.token = comment; + advance(); //skip the closing slash + return Token::Whitespace; } - return Token::Whitespace; + // we actually have a multiline documentation comment + Token::Value comment; + m_nextSkippedComment.location.start = firstSlashPosition; + comment = scanMultiLineDocComment(); + m_nextSkippedComment.location.end = sourcePos(); + m_nextSkippedComment.token = comment; + if (comment == Token::Illegal) + return Token::Illegal; + else + return Token::Whitespace; } else return skipMultiLineComment(); @@ -670,18 +677,38 @@ bool Scanner::scanEscape() if (!scanHexByte(c)) return false; break; + default: + return false; } addLiteralChar(c); return true; } +bool Scanner::isUnicodeLinebreak() +{ + if (0x0a <= m_char && m_char <= 0x0d) + // line feed, vertical tab, form feed, carriage return + return true; + else if (!m_source.isPastEndOfInput(1) && uint8_t(m_source.get(0)) == 0xc2 && uint8_t(m_source.get(1)) == 0x85) + // NEL - U+0085, C2 85 in utf8 + return true; + else if (!m_source.isPastEndOfInput(2) && uint8_t(m_source.get(0)) == 0xe2 && uint8_t(m_source.get(1)) == 0x80 && ( + uint8_t(m_source.get(2)) == 0xa8 || uint8_t(m_source.get(2)) == 0xa9 + )) + // LS - U+2028, E2 80 A8 in utf8 + // PS - U+2029, E2 80 A9 in utf8 + return true; + else + return false; +} + Token::Value Scanner::scanString() { char const quote = m_char; advance(); // consume quote LiteralScope literal(this, LITERAL_TYPE_STRING); - while (m_char != quote && !isSourcePastEndOfInput() && !isLineTerminator(m_char)) + while (m_char != quote && !isSourcePastEndOfInput() && !isUnicodeLinebreak()) { char c = m_char; advance(); @@ -705,7 +732,7 @@ Token::Value Scanner::scanHexString() char const quote = m_char; advance(); // consume quote LiteralScope literal(this, LITERAL_TYPE_STRING); - while (m_char != quote && !isSourcePastEndOfInput() && !isLineTerminator(m_char)) + while (m_char != quote && !isSourcePastEndOfInput()) { char c = m_char; if (!scanHexByte(c)) diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h index 0adaa6fd..602532e4 100644 --- a/libsolidity/parsing/Scanner.h +++ b/libsolidity/parsing/Scanner.h @@ -197,8 +197,8 @@ private: /// Skips all whitespace and @returns true if something was skipped. bool skipWhitespace(); - /// Skips all whitespace except Line feeds and returns true if something was skipped - bool skipWhitespaceExceptLF(); + /// Skips all whitespace that are neither '\r' nor '\n'. + void skipWhitespaceExceptUnicodeLinebreak(); Token::Value skipSingleLineComment(); Token::Value skipMultiLineComment(); @@ -218,6 +218,9 @@ private: /// is scanned. bool scanEscape(); + /// @returns true iff we are currently positioned at a unicode line break. + bool isUnicodeLinebreak(); + /// Return the current source position. int sourcePos() const { return m_source.position(); } bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); } diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 020bce7f..e216ef01 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -393,6 +393,14 @@ BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string) BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); } +BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) +{ + // This used to parse as "comment", "identifier" + Scanner scanner(CharStream("/** / x")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 30578cad8108216598091ead7dde2acce68924ef Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 16:42:39 +0200 Subject: Tests. --- test/libsolidity/SolidityScanner.cpp | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index e216ef01..4ccc6788 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -23,6 +23,8 @@ #include #include +using namespace std; + namespace dev { namespace solidity @@ -401,6 +403,102 @@ BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } +BOOST_AUTO_TEST_CASE(multiline_doc_comment_at_eos) +{ + // This used to parse as "whitespace" + Scanner scanner(CharStream("/**")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(multiline_comment_at_eos) +{ + Scanner scanner(CharStream("/*")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + +BOOST_AUTO_TEST_CASE(regular_line_break_in_single_line_comment) +{ + for (auto const& nl: {"\r", "\n"}) + { + Scanner scanner(CharStream("// abc " + string(nl) + " def ")); + BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} + +BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_comment) +{ + for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) + { + Scanner scanner(CharStream("// abc " + string(nl) + " def ")); + BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + for (size_t i = 0; i < string(nl).size() - 1; i++) + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} + +BOOST_AUTO_TEST_CASE(regular_line_breaks_in_single_line_doc_comment) +{ + for (auto const& nl: {"\r", "\n"}) + { + Scanner scanner(CharStream("/// abc " + string(nl) + " def ")); + BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "abc "); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} + +BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_doc_comment) +{ + for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) + { + Scanner scanner(CharStream("/// abc " + string(nl) + " def ")); + BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "abc "); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + for (size_t i = 0; i < string(nl).size() - 1; i++) + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} + +BOOST_AUTO_TEST_CASE(regular_line_breaks_in_strings) +{ + for (auto const& nl: {"\n", "\r"}) + { + Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} + +BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_strings) +{ + for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) + { + Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + for (size_t i = 0; i < string(nl).size(); i++) + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); + } +} BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 55e4532c7231ea7f4ab54402ebac84406564b64b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 16:44:59 +0200 Subject: Changelog. --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 26f7d5e2..1a02ade5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,9 @@ Bugfixes: * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. + * Parser: Treat unicode line endings as terminating strings and single-line comments. + * Parser: Disallow unterminated multi-line comments at the end of input. + * Parser: Treat ``/** /`` as unterminated multi-line comment. ### 0.4.24 (2018-05-16) -- cgit v1.2.3 From f190caf538f25baa200195baf6f7444927faf926 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 4 Sep 2018 16:51:17 +0200 Subject: Tests. --- test/libsolidity/SolidityEndToEndTest.cpp | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a4b59761..f2cc78bf 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10743,6 +10743,46 @@ BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) ABI_CHECK(callContractFunction("right(uint8)", 8 * 8), encodeArgs(string(8, 0) + "123456789012")); } +BOOST_AUTO_TEST_CASE(exp_cleanup) +{ + char const* sourceCode = R"( + contract C { + function f() public pure returns (uint8 x) { + uint8 y = uint8(2) ** uint8(8); + return 0 ** y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1))); +} + +BOOST_AUTO_TEST_CASE(exp_cleanup_direct) +{ + char const* sourceCode = R"( + contract C { + function f() public pure returns (uint8 x) { + return uint8(0) ** uint8(uint8(2) ** uint8(8)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1))); +} + +BOOST_AUTO_TEST_CASE(exp_cleanup_nonzero_base) +{ + char const* sourceCode = R"( + contract C { + function f() public pure returns (uint8 x) { + return uint8(0x166) ** uint8(uint8(2) ** uint8(8)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1))); +} + BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) { char const* sourceCode = R"( -- cgit v1.2.3 From eb7978d6314b51b3b00dbc6155cedd799a5cd767 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 4 Sep 2018 16:51:22 +0200 Subject: Always perform cleanup for EXP. --- libsolidity/codegen/ExpressionCompiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 4bcc1fa9..f38c1e67 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2069,7 +2069,9 @@ bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _ { if (Token::isCompareOp(_op) || Token::isShiftOp(_op)) return true; - else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod)) + else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod || _op == Token::Exp)) + // We need cleanup for EXP because 0**0 == 1, but 0**0x100 == 0 + // It would suffice to clean the exponent, though. return true; else return false; -- cgit v1.2.3 From be713ed1176c4dee2c1e444d41e5a72ab9caf115 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 4 Sep 2018 16:55:45 +0200 Subject: Changelog entry and bug list. --- Changelog.md | 3 ++- docs/bugs.json | 7 ++++++ docs/bugs_by_version.json | 55 +++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index 2a04c8a1..05e0e5eb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.25 (unreleased) -Bugfixes: +Important Bugfixes: + * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. * Parser: Treat unicode line endings as terminating strings and single-line comments. diff --git a/docs/bugs.json b/docs/bugs.json index 423c314d..d0704c1f 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -7,6 +7,13 @@ "fixed": "0.4.25", "severity": "very low" }, + { + "name": "ExpCleanupZero", + "summary": "Using exponentiating with types shorter than 256 bits and zero as base can result in unexpected values.", + "description": "As defined by the EVM, 0 ** 0 is one. Solidity does not always remove dirty higher order bits of types that are smaller than 256 bits before applying an operation because it does not matter if the cleanup is performed before or after the operation. This is true for EXP except for the case where the base is zero, which was overlooked.", + "fixed": "0.4.25", + "severity": "high" + }, { "name": "OneOfTwoConstructorsSkipped", "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 00531b9e..5bd43415 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -18,6 +19,7 @@ }, "0.1.1": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -35,6 +37,7 @@ }, "0.1.2": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -52,6 +55,7 @@ }, "0.1.3": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -69,6 +73,7 @@ }, "0.1.4": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -86,6 +91,7 @@ }, "0.1.5": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -103,6 +109,7 @@ }, "0.1.6": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -121,6 +128,7 @@ }, "0.1.7": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -139,6 +147,7 @@ }, "0.2.0": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -157,6 +166,7 @@ }, "0.2.1": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -175,6 +185,7 @@ }, "0.2.2": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -193,6 +204,7 @@ }, "0.3.0": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -211,6 +223,7 @@ }, "0.3.1": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -228,6 +241,7 @@ }, "0.3.2": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -245,6 +259,7 @@ }, "0.3.3": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -261,6 +276,7 @@ }, "0.3.4": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -277,6 +293,7 @@ }, "0.3.5": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -293,6 +310,7 @@ }, "0.3.6": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -307,6 +325,7 @@ }, "0.4.0": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -321,6 +340,7 @@ }, "0.4.1": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -335,6 +355,7 @@ }, "0.4.10": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -345,6 +366,7 @@ }, "0.4.11": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -354,6 +376,7 @@ }, "0.4.12": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -362,6 +385,7 @@ }, "0.4.13": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -370,6 +394,7 @@ }, "0.4.14": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue" ], @@ -377,12 +402,14 @@ }, "0.4.15": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector" ], "released": "2017-08-08" }, "0.4.16": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector" ], "released": "2017-08-24" @@ -390,24 +417,28 @@ "0.4.17": { "bugs": [ "EventStructWrongData", + "ExpCleanupZero", "ZeroFunctionSelector" ], "released": "2017-09-21" }, "0.4.18": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2017-10-18" }, "0.4.19": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2017-11-30" }, "0.4.2": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -421,37 +452,43 @@ }, "0.4.20": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2018-02-14" }, "0.4.21": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2018-03-07" }, "0.4.22": { "bugs": [ "EventStructWrongData", + "ExpCleanupZero", "OneOfTwoConstructorsSkipped" ], "released": "2018-04-16" }, "0.4.23": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2018-04-19" }, "0.4.24": { "bugs": [ - "EventStructWrongData" + "EventStructWrongData", + "ExpCleanupZero" ], "released": "2018-05-16" }, "0.4.3": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -464,6 +501,7 @@ }, "0.4.4": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -475,6 +513,7 @@ }, "0.4.5": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -487,6 +526,7 @@ }, "0.4.6": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -498,6 +538,7 @@ }, "0.4.7": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -508,6 +549,7 @@ }, "0.4.8": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -518,6 +560,7 @@ }, "0.4.9": { "bugs": [ + "ExpCleanupZero", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", -- cgit v1.2.3 From 3b7be594cf046cc34864cefbd3cf0f5159770163 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 6 Sep 2018 17:30:51 +0200 Subject: Update bug description, add regex and tests. --- docs/bugs.json | 9 +-- docs/bugs_by_version.json | 86 ++++++++++++------------- test/buglist_test_vectors.md | 148 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 47 deletions(-) create mode 100644 test/buglist_test_vectors.md diff --git a/docs/bugs.json b/docs/bugs.json index d0704c1f..560176d1 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -8,11 +8,12 @@ "severity": "very low" }, { - "name": "ExpCleanupZero", - "summary": "Using exponentiating with types shorter than 256 bits and zero as base can result in unexpected values.", - "description": "As defined by the EVM, 0 ** 0 is one. Solidity does not always remove dirty higher order bits of types that are smaller than 256 bits before applying an operation because it does not matter if the cleanup is performed before or after the operation. This is true for EXP except for the case where the base is zero, which was overlooked.", + "name": "ExpExponentCleanup", + "summary": "Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.", + "description": "Higher order bits in the exponent are not properly cleaned before the EXP opcode is applied if the type of the exponent expression is smaller than 256 bits and not smaller than the type of the base. In that case, the result might be larger than expected if the exponent is assumed to lie within the value range of the type. Literal numbers as exponents are unaffected as are exponents or bases of type uint256.", "fixed": "0.4.25", - "severity": "high" + "severity": "medium/high", + "check": {"regex-source": "[^/]\\*\\* *[^/0-9 ]"} }, { "name": "OneOfTwoConstructorsSkipped", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 5bd43415..d678bf21 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,7 +1,7 @@ { "0.1.0": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -19,7 +19,7 @@ }, "0.1.1": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -37,7 +37,7 @@ }, "0.1.2": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -55,7 +55,7 @@ }, "0.1.3": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -73,7 +73,7 @@ }, "0.1.4": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -91,7 +91,7 @@ }, "0.1.5": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -109,7 +109,7 @@ }, "0.1.6": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -128,7 +128,7 @@ }, "0.1.7": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -147,7 +147,7 @@ }, "0.2.0": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -166,7 +166,7 @@ }, "0.2.1": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -185,7 +185,7 @@ }, "0.2.2": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -204,7 +204,7 @@ }, "0.3.0": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -223,7 +223,7 @@ }, "0.3.1": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -241,7 +241,7 @@ }, "0.3.2": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -259,7 +259,7 @@ }, "0.3.3": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -276,7 +276,7 @@ }, "0.3.4": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -293,7 +293,7 @@ }, "0.3.5": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -310,7 +310,7 @@ }, "0.3.6": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -325,7 +325,7 @@ }, "0.4.0": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -340,7 +340,7 @@ }, "0.4.1": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -355,7 +355,7 @@ }, "0.4.10": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -366,7 +366,7 @@ }, "0.4.11": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -376,7 +376,7 @@ }, "0.4.12": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -385,7 +385,7 @@ }, "0.4.13": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -394,7 +394,7 @@ }, "0.4.14": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue" ], @@ -402,14 +402,14 @@ }, "0.4.15": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector" ], "released": "2017-08-08" }, "0.4.16": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector" ], "released": "2017-08-24" @@ -417,7 +417,7 @@ "0.4.17": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector" ], "released": "2017-09-21" @@ -425,20 +425,20 @@ "0.4.18": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2017-10-18" }, "0.4.19": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2017-11-30" }, "0.4.2": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -453,21 +453,21 @@ "0.4.20": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2018-02-14" }, "0.4.21": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2018-03-07" }, "0.4.22": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero", + "ExpExponentCleanup", "OneOfTwoConstructorsSkipped" ], "released": "2018-04-16" @@ -475,20 +475,20 @@ "0.4.23": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2018-04-19" }, "0.4.24": { "bugs": [ "EventStructWrongData", - "ExpCleanupZero" + "ExpExponentCleanup" ], "released": "2018-05-16" }, "0.4.3": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -501,7 +501,7 @@ }, "0.4.4": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -513,7 +513,7 @@ }, "0.4.5": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -526,7 +526,7 @@ }, "0.4.6": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -538,7 +538,7 @@ }, "0.4.7": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -549,7 +549,7 @@ }, "0.4.8": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -560,7 +560,7 @@ }, "0.4.9": { "bugs": [ - "ExpCleanupZero", + "ExpExponentCleanup", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", diff --git a/test/buglist_test_vectors.md b/test/buglist_test_vectors.md new file mode 100644 index 00000000..e683f481 --- /dev/null +++ b/test/buglist_test_vectors.md @@ -0,0 +1,148 @@ +# NestedArrayFunctionCallDecoder + +## buggy + +function f() pure returns (uint[2][2]) { } + +-- + +function f() returns (uint[2][2] a) { } + +-- + +function f() returns (uint x, uint[200][2] a) { } + +-- + +function f() returns (uint[200][2] a, uint x) { } + +-- + +function f() returns (uint[200][2] a, uint x); + +-- + +function f() returns ( + uint + [ + 200 + ] + [2] + a, uint x); + +-- + +function f() returns ( + uint + [ + ContractName.ConstantName + ] + [2] + a, uint x); + +## fine + +function f() returns (uint[2]) { } + +-- + +function f() public pure returns (uint[2][] a) { } + +-- + +function f() public pure returns (uint[ 2 ] [ ] a) { } + +-- + +function f() public pure returns (uint x, uint[] a) { } + +-- + +function f(uint[2][2]) { } + +-- + +function f() m(uint[2][2]) { } + +-- + +function f() returns (uint, uint) { uint[2][2] memory x; } + +# ExpExponentCleanup + +## buggy + +x ** y + +-- + +x ** uint8(y) + +-- + +x**y + +## fine + +x ** 2 + +-- + +x**2 + +-- + +x**200 + +-- + +/** bla **/ + +-- + +/**/ + +# EventStructWrongData + +## buggy + +pragma experimental ABIEncoderV2; +contract C +{ + struct S { uint x; } + event E(S); + event F(S); + enum A { B, C } + event G(A); + function f(S s); +} + +-- + +pragma experimental ABIEncoderV2; +contract C +{ + struct S { uint x; } + event E(S indexed); + event F(uint, S, bool); +} + +## fine + +pragma experimental ABIEncoderV2; +contract C +{ + struct S { uint x; } + enum A { B, C } + event G(A); +} + +-- + +pragma experimental ABIEncoderV2; +contract C +{ + struct S { uint x; } + function f(S s); + S s1; +} -- cgit v1.2.3 From 69320472afe8c1c5031c3243ef6299cbfcd2e523 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 21 Aug 2018 16:09:53 +0200 Subject: Buglist check script supports json paths --- circle.yml | 17 ++++++ docs/bugs.json | 26 ++++++--- docs/bugs.rst | 13 +++++ docs/bugs_by_version.json | 56 +++++++++++++++---- test/buglistTests.js | 134 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 228 insertions(+), 18 deletions(-) create mode 100755 test/buglistTests.js diff --git a/circle.yml b/circle.yml index 4ce3082b..fb504ba1 100644 --- a/circle.yml +++ b/circle.yml @@ -155,6 +155,23 @@ jobs: - store_artifacts: *solc_artifact - persist_to_workspace: *all_artifacts + test_buglist: + docker: + - image: circleci/node + environment: + TERM: xterm + steps: + - checkout + - run: + name: JS deps + command: | + npm install download + npm install JSONPath + npm install mktemp + - run: + name: Test buglist + command: ./test/buglistTests.js + test_x86_linux: docker: - image: buildpack-deps:artful diff --git a/docs/bugs.json b/docs/bugs.json index 560176d1..28c0fe62 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,12 +1,4 @@ [ - { - "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.4.25", - "severity": "very low" - }, { "name": "ExpExponentCleanup", "summary": "Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.", @@ -15,6 +7,24 @@ "severity": "medium/high", "check": {"regex-source": "[^/]\\*\\* *[^/0-9 ]"} }, + { + "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.4.25", + "severity": "very low", + "check": {"ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"} + }, + { + "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.", + "introduced": "0.1.4", + "fixed": "0.4.22", + "severity": "medium", + "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} + }, { "name": "OneOfTwoConstructorsSkipped", "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.", diff --git a/docs/bugs.rst b/docs/bugs.rst index 7629830d..f7522183 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -56,6 +56,19 @@ conditions is an object that can contain a boolean value ``optimizer``, which means that the optimizer has to be switched on to enable the bug. If no conditions are given, assume that the bug is present. +check + This field contains different checks that report whether the smart contract + contains the bug or not. The first type of check are Javascript regular + expressions that are to be matched against the source code ("source-regex") + if the bug is present. If there is no match, then the bug is very likely + not present. If there is a match, the bug might be present. For improved + accuracy, the checks should be applied to the source code after stripping + comments. + The second type of check are patterns to be checked on the compact AST of + the Solidity program ("ast-compact-json-path"). The specified search query + is a `JsonPath `_ expression. + If at least one path of the Solidity AST matches the query, the bug is + likely present. .. literalinclude:: bugs.json :language: js diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index d678bf21..88a480b2 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -74,6 +74,7 @@ "0.1.4": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -92,6 +93,7 @@ "0.1.5": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -110,6 +112,7 @@ "0.1.6": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -129,6 +132,7 @@ "0.1.7": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -148,6 +152,7 @@ "0.2.0": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -167,6 +172,7 @@ "0.2.1": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -186,6 +192,7 @@ "0.2.2": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -205,6 +212,7 @@ "0.3.0": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -224,6 +232,7 @@ "0.3.1": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -242,6 +251,7 @@ "0.3.2": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -260,6 +270,7 @@ "0.3.3": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -277,6 +288,7 @@ "0.3.4": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -294,6 +306,7 @@ "0.3.5": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -311,6 +324,7 @@ "0.3.6": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -326,6 +340,7 @@ "0.4.0": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -341,6 +356,7 @@ "0.4.1": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -356,6 +372,7 @@ "0.4.10": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -367,6 +384,7 @@ "0.4.11": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -377,6 +395,7 @@ "0.4.12": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -386,6 +405,7 @@ "0.4.13": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -395,6 +415,7 @@ "0.4.14": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue" ], @@ -403,6 +424,7 @@ "0.4.15": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-08" @@ -410,35 +432,40 @@ "0.4.16": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-24" }, "0.4.17": { "bugs": [ - "EventStructWrongData", "ExpExponentCleanup", + "EventStructWrongData", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-09-21" }, "0.4.18": { "bugs": [ + "ExpExponentCleanup", "EventStructWrongData", - "ExpExponentCleanup" + "NestedArrayFunctionCallDecoder" ], "released": "2017-10-18" }, "0.4.19": { "bugs": [ + "ExpExponentCleanup", "EventStructWrongData", - "ExpExponentCleanup" + "NestedArrayFunctionCallDecoder" ], "released": "2017-11-30" }, "0.4.2": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -452,43 +479,46 @@ }, "0.4.20": { "bugs": [ + "ExpExponentCleanup", "EventStructWrongData", - "ExpExponentCleanup" + "NestedArrayFunctionCallDecoder" ], "released": "2018-02-14" }, "0.4.21": { "bugs": [ + "ExpExponentCleanup", "EventStructWrongData", - "ExpExponentCleanup" + "NestedArrayFunctionCallDecoder" ], "released": "2018-03-07" }, "0.4.22": { "bugs": [ - "EventStructWrongData", "ExpExponentCleanup", + "EventStructWrongData", "OneOfTwoConstructorsSkipped" ], "released": "2018-04-16" }, "0.4.23": { "bugs": [ - "EventStructWrongData", - "ExpExponentCleanup" + "ExpExponentCleanup", + "EventStructWrongData" ], "released": "2018-04-19" }, "0.4.24": { "bugs": [ - "EventStructWrongData", - "ExpExponentCleanup" + "ExpExponentCleanup", + "EventStructWrongData" ], "released": "2018-05-16" }, "0.4.3": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -502,6 +532,7 @@ "0.4.4": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -514,6 +545,7 @@ "0.4.5": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -527,6 +559,7 @@ "0.4.6": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -539,6 +572,7 @@ "0.4.7": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -550,6 +584,7 @@ "0.4.8": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -561,6 +596,7 @@ "0.4.9": { "bugs": [ "ExpExponentCleanup", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", diff --git a/test/buglistTests.js b/test/buglistTests.js new file mode 100755 index 00000000..f24f0cb6 --- /dev/null +++ b/test/buglistTests.js @@ -0,0 +1,134 @@ +#!/usr/bin/env node + +"use strict"; + +var util = require('util') +var exec = util.promisify(require('child_process').exec) +var mktemp = require('mktemp'); +var download = require('download') +var JSONPath = require('JSONPath') +var fs = require('fs') +var bugs = JSON.parse(fs.readFileSync(__dirname + '/../docs/bugs.json', 'utf8')) + +var bugsByName = {} +for (var i in bugs) +{ + if (bugs[i].name in bugsByName) + { + throw "Duplicate bug name: " + bugs[i].name + } + bugsByName[bugs[i].name] = bugs[i] +} + +var tests = fs.readFileSync(__dirname + '/buglist_test_vectors.md', 'utf8') + +var testVectorParser = /\s*#\s+(\S+)\s+## buggy\n([^#]*)## fine\n([^#]*)/g + +runTests() + +async function runTests() +{ + var result; + while ((result = testVectorParser.exec(tests)) !== null) + { + var name = result[1] + var buggy = result[2].split('\n--\n') + var fine = result[3].split('\n--\n') + console.log("Testing " + name + " with " + buggy.length + " buggy and " + fine.length + " fine instances") + + try { + await checkRegex(name, buggy, fine) + await checkJSONPath(name, buggy, fine) + } catch (err) { + console.error("Error: " + err) + } + } +} + +function checkRegex(name, buggy, fine) +{ + return new Promise(function(resolve, reject) { + var regexStr = bugsByName[name].check['regex-source'] + if (regexStr !== undefined) + { + var regex = RegExp(regexStr) + for (var i in buggy) + { + if (!regex.exec(buggy[i])) + { + reject("Bug " + name + ": Buggy source does not match: " + buggy[i]) + } + } + for (var i in fine) + { + if (regex.exec(fine[i])) + { + reject("Bug " + name + ": Non-buggy source matches: " + fine[i]) + } + } + } + resolve() + }) +} + +async function checkJSONPath(name, buggy, fine) +{ + var jsonPath = bugsByName[name].check['ast-compact-json-path'] + if (jsonPath !== undefined) + { + var url = "http://github.com/ethereum/solidity/releases/download/v" + bugsByName[name].introduced + "/solc-static-linux" + try { + var tmpdir = await mktemp.createDir('XXXXX') + var binary = tmpdir + "/solc-static-linux" + await download(url, tmpdir) + exec("chmod +x " + binary) + for (var i in buggy) + { + var result = await checkJsonPathTest(buggy[i], tmpdir, binary, jsonPath, i) + if (!result) + throw "Bug " + name + ": Buggy source does not contain path: " + buggy[i] + } + for (var i in fine) + { + var result = await checkJsonPathTest(fine[i], tmpdir, binary, jsonPath, i + buggy.length) + if (result) + throw "Bug " + name + ": Non-buggy source contains path: " + fine[i] + } + exec("rm -r " + tmpdir) + } catch (err) { + throw err + } + } +} + +function checkJsonPathTest(code, tmpdir, binary, query, idx) { + return new Promise(function(resolve, reject) { + var solFile = tmpdir + "/jsonPath" + idx + ".sol" + var astFile = tmpdir + "/ast" + idx + ".json" + writeFilePromise(solFile, code) + .then(() => { + return exec(binary + " --ast-compact-json " + solFile + " > " + astFile) + }) + .then(() => { + var jsonRE = /(\{[\s\S]*\})/ + var ast = JSON.parse(jsonRE.exec(fs.readFileSync(astFile, 'utf8'))[0]) + var result = JSONPath({json: ast, path: query}) + if (result.length > 0) + resolve(true) + else + resolve(false) + }) + .catch((err) => { + reject(err) + }) + }) +} + +function writeFilePromise(filename, data) { + return new Promise(function(resolve, reject) { + fs.writeFile(filename, data, 'utf8', function(err) { + if (err) reject(err) + else resolve(data) + }) + }) +} -- cgit v1.2.3 From 75e38be05035ecbcb7c77bde53dbc6cbc22e88d4 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 25 Jul 2018 15:53:03 +0200 Subject: Bugfix entry regarding nested arrays returned by library functions --- circle.yml | 1 + docs/bugs.json | 20 ++++++++++++++------ docs/bugs.rst | 9 +++++---- docs/bugs_by_version.json | 11 +++++++++++ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/circle.yml b/circle.yml index fb504ba1..7c95fa7f 100644 --- a/circle.yml +++ b/circle.yml @@ -234,6 +234,7 @@ workflows: version: 2 build_all: jobs: + - test_buglist: *build_on_tags - build_emscripten: *build_on_tags - test_emscripten_solcjs: <<: *build_on_tags diff --git a/docs/bugs.json b/docs/bugs.json index 28c0fe62..c1e377a4 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -17,13 +17,12 @@ "check": {"ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"} }, { - "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.", - "introduced": "0.1.4", + "name": "PublicLibFunctionsDoNotReturnNestedArrays", + "summary": "Calls to public library functions (internal functions are safe) that return nested arrays return only zeroes.", + "description": "The compiler does not complain about public library functions (internal functions are safe) returning nested arrays, but it also does not return it correctly. Thus, the function caller receives only zeroes.", + "introduced": "0.4.11", "fixed": "0.4.22", - "severity": "medium", - "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} + "severity": "low" }, { "name": "OneOfTwoConstructorsSkipped", @@ -33,6 +32,15 @@ "fixed": "0.4.23", "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.", + "introduced": "0.1.4", + "fixed": "0.4.22", + "severity": "medium", + "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} + }, { "name": "ZeroFunctionSelector", "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.", diff --git a/docs/bugs.rst b/docs/bugs.rst index f7522183..8e3382c8 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -57,14 +57,15 @@ conditions means that the optimizer has to be switched on to enable the bug. If no conditions are given, assume that the bug is present. check - This field contains different checks that report whether the smart contract + This field contains different checks that can be used to determine + whether a smart contract contains the bug or not. The first type of check are Javascript regular - expressions that are to be matched against the source code ("source-regex") - if the bug is present. If there is no match, then the bug is very likely + expressions that are to be matched against the source code ("source-regex"). + If there is no match, then the bug is very likely not present. If there is a match, the bug might be present. For improved accuracy, the checks should be applied to the source code after stripping comments. - The second type of check are patterns to be checked on the compact AST of + The second type of check are patterns to be applied to the compact AST of the Solidity program ("ast-compact-json-path"). The specified search query is a `JsonPath `_ expression. If at least one path of the Solidity AST matches the query, the bug is diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 88a480b2..90879db9 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -384,6 +384,7 @@ "0.4.11": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", @@ -395,6 +396,7 @@ "0.4.12": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", @@ -405,6 +407,7 @@ "0.4.13": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", @@ -415,6 +418,7 @@ "0.4.14": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue" @@ -424,6 +428,7 @@ "0.4.15": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], @@ -432,6 +437,7 @@ "0.4.16": { "bugs": [ "ExpExponentCleanup", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], @@ -441,6 +447,7 @@ "bugs": [ "ExpExponentCleanup", "EventStructWrongData", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], @@ -450,6 +457,7 @@ "bugs": [ "ExpExponentCleanup", "EventStructWrongData", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder" ], "released": "2017-10-18" @@ -458,6 +466,7 @@ "bugs": [ "ExpExponentCleanup", "EventStructWrongData", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder" ], "released": "2017-11-30" @@ -481,6 +490,7 @@ "bugs": [ "ExpExponentCleanup", "EventStructWrongData", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder" ], "released": "2018-02-14" @@ -489,6 +499,7 @@ "bugs": [ "ExpExponentCleanup", "EventStructWrongData", + "PublicLibFunctionsDoNotReturnNestedArrays", "NestedArrayFunctionCallDecoder" ], "released": "2018-03-07" -- cgit v1.2.3 From 8c56a5912b49000fbb66bdb8c5ad63131bfa9f30 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 12 Sep 2018 18:38:16 +0200 Subject: Set relase date of 0.4.25. --- Changelog.md | 2 +- docs/bugs_by_version.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 05e0e5eb..29c28e30 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.4.25 (unreleased) +### 0.4.25 (2018-09-12) Important Bugfixes: * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 90879db9..ef084660 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -526,6 +526,10 @@ ], "released": "2018-05-16" }, + "0.4.25": { + "bugs": [], + "released": "2018-09-12" + }, "0.4.3": { "bugs": [ "ExpExponentCleanup", -- cgit v1.2.3 From 73973d2448fd0965b3aa988d18397e9dce6d949d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 17 May 2018 14:42:22 +0200 Subject: CMake: Fix libdir for jsoncpp external project in special case When building on Debian/Ubuntu with install prefix /usr (e.g. in PPA builds) the CMAKE_INSTALL_LIBDIR is resolved to lib/x86_64-linux-gnu. For jsoncpp external project this is never the case because the install prefix is not /usr. Remove multiarch part from libdir if there. --- cmake/jsoncpp.cmake | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index 3d6b37ed..cc2da7e7 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -7,8 +7,14 @@ else() endif() include(GNUInstallDirs) +set(libdir ${CMAKE_INSTALL_LIBDIR}) +if(CMAKE_LIBRARY_ARCHITECTURE) + # Do not use Debian multiarch library dir. + string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" libdir ${libdir}) +endif() + set(prefix "${CMAKE_BINARY_DIR}/deps") -set(JSONCPP_LIBRARY "${prefix}/${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(JSONCPP_LIBRARY "${prefix}/${libdir}/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") set(JSONCPP_INCLUDE_DIR "${prefix}/include") if(NOT MSVC) -- cgit v1.2.3 From 1a5f90954a203db2dab53a569e9e6912457cee96 Mon Sep 17 00:00:00 2001 From: mingchuan Date: Wed, 6 Jun 2018 14:03:07 +0800 Subject: Fix cmake when custom CMAKE_INSTALL_LIBDIR is given According to cmake documents, we cannot assume CMAKE_INSTALL_LIBDIR is a relative path. This commit fixes the "no rule to make libjsoncpp.a" error by passing -DCMAKE_INSTALL_LIBDIR=lib to jsoncpp external project. --- cmake/jsoncpp.cmake | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index cc2da7e7..0c110b53 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -6,15 +6,8 @@ else() set(JSONCPP_CMAKE_COMMAND ${CMAKE_COMMAND}) endif() -include(GNUInstallDirs) -set(libdir ${CMAKE_INSTALL_LIBDIR}) -if(CMAKE_LIBRARY_ARCHITECTURE) - # Do not use Debian multiarch library dir. - string(REPLACE "/${CMAKE_LIBRARY_ARCHITECTURE}" "" libdir ${libdir}) -endif() - set(prefix "${CMAKE_BINARY_DIR}/deps") -set(JSONCPP_LIBRARY "${prefix}/${libdir}/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") set(JSONCPP_INCLUDE_DIR "${prefix}/include") if(NOT MSVC) @@ -36,6 +29,7 @@ ExternalProject_Add(jsoncpp-project CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_INSTALL_LIBDIR=lib # Build static lib but suitable to be included in a shared lib. -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} -DJSONCPP_WITH_TESTS=OFF -- cgit v1.2.3 From 72b9ad6837b6d080e1646dbbd58219630fbf0021 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 10 Jul 2018 15:12:32 +0200 Subject: Visual Studio 2017 build-time (linking) fix and improvements --- .gitignore | 3 +++ cmake/EthCompilerSettings.cmake | 11 ----------- cmake/jsoncpp.cmake | 4 +--- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 14c227d0..87a3e593 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ build/ docs/_build docs/utils/__pycache__ docs/utils/*.pyc +/deps/downloads/ # vim stuff *.swp @@ -43,3 +44,5 @@ docs/utils/*.pyc .idea browse.VC.db CMakeLists.txt.user +/CMakeSettings.json +/.vs diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 683d1d2e..3ae5bf2a 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -132,17 +132,6 @@ elseif (DEFINED MSVC) add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions - # Always use Release variant of C++ runtime. - # We don't want to provide Debug variants of all dependencies. Some default - # flags set by CMake must be tweaked. - string(REPLACE "/MDd" "/MD" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/D_DEBUG" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") - string(REPLACE "/MDd" "/MD" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - string(REPLACE "/D_DEBUG" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") - set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS OFF) - # disable empty object file warning set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") # warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index 0c110b53..e886c609 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -35,9 +35,7 @@ ExternalProject_Add(jsoncpp-project -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF -DCMAKE_CXX_FLAGS=${JSONCPP_EXTRA_FLAGS} - # Overwrite build and install commands to force Release build on MSVC. - BUILD_COMMAND cmake --build --config Release - INSTALL_COMMAND cmake --build --config Release --target install + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${byproducts} ) -- cgit v1.2.3 From d2d9162bb95c2d3eb2ae57422b24ca5c3b69a935 Mon Sep 17 00:00:00 2001 From: Guido Vranken Date: Thu, 19 Jul 2018 00:05:45 +0200 Subject: Propagate original CMAKE_CXX_FLAGS to jsoncpp compilation --- cmake/jsoncpp.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index e886c609..a6ca0e7f 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -34,7 +34,7 @@ ExternalProject_Add(jsoncpp-project -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DCMAKE_CXX_FLAGS=${JSONCPP_EXTRA_FLAGS} + -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} ${JSONCPP_EXTRA_FLAGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${byproducts} ) -- cgit v1.2.3 From 84d92450767480dcd0748c781e3cbda8e4a82ebd Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 3 Aug 2018 16:50:08 +0200 Subject: Rename JSONCPP_EXTRA_FLAGS to JSONCPP_CXX_FLAGS, add EMSCRIPTEN workaround and remove obsolete MSVC workaround. --- cmake/jsoncpp.cmake | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index a6ca0e7f..ea3218ef 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -10,8 +10,16 @@ set(prefix "${CMAKE_BINARY_DIR}/deps") set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") set(JSONCPP_INCLUDE_DIR "${prefix}/include") -if(NOT MSVC) - set(JSONCPP_EXTRA_FLAGS "-std=c++11") +# TODO: Investigate why this breaks some emscripten builds and +# check whether this can be removed after updating the emscripten +# versions used in the CI runs. +if(EMSCRIPTEN) + # Do not include all flags in CMAKE_CXX_FLAGS for emscripten, + # but only use -std=c++11. Using all flags causes build failures + # at the moment. + set(JSONCPP_CXX_FLAGS -std=c++11) +else() + set(JSONCPP_CXX_FLAGS ${CMAKE_CXX_FLAGS}) endif() set(byproducts "") @@ -34,7 +42,7 @@ ExternalProject_Add(jsoncpp-project -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} ${JSONCPP_EXTRA_FLAGS} + -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${byproducts} ) -- cgit v1.2.3 From 6ed88d1bfe9e92e8b34c4f933467aa4a1f056dd7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 13 Sep 2018 16:34:22 +0200 Subject: Update changelog. --- Changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 29c28e30..bfe82f8c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,7 +4,8 @@ Important Bugfixes: * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. - * Parser: Treat unicode line endings as terminating strings and single-line comments. + * Parser: Consider all unicode line terminators (LF, VF, FF, CR, NEL, LS, PS) for single-line comments + and string literals. They are invalid in strings and will end comments. * Parser: Disallow unterminated multi-line comments at the end of input. * Parser: Treat ``/** /`` as unterminated multi-line comment. -- cgit v1.2.3