From dc1c0e9d4e2dd3ba557602aac5cf67b0f9d76c0a Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Thu, 10 Dec 2020 12:43:46 +0100 Subject: [PATCH 01/29] Abiv2 fuzzer: Retrieve values to be encoded from the fuzzer --- test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp | 24 ++++++- test/tools/ossfuzz/abiV2Proto.proto | 6 +- test/tools/ossfuzz/protoToAbiV2.cpp | 80 +++++++++++++++++++--- test/tools/ossfuzz/protoToAbiV2.h | 69 ++++++++++++++----- 4 files changed, 144 insertions(+), 35 deletions(-) diff --git a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp index e1310ea11..4e28c444b 100644 --- a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp +++ b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp @@ -28,10 +28,28 @@ using namespace std; static constexpr size_t abiCoderHeapSize = 1024 * 512; -DEFINE_PROTO_FUZZER(Contract const&) +DEFINE_PROTO_FUZZER(Contract const& _contract) { + ProtoConverter converter; + string contractSource = converter.contractToString(_contract); + + if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) + { + // With libFuzzer binary run this to generate the solidity source file x.sol from a proto input: + // PROTO_FUZZER_DUMP_PATH=x.sol ./a.out proto-input + ofstream of(dump_path); + of << contractSource; + } + + string typeString = converter.isabelleTypeString(); + string valueString = converter.isabelleValueString(); + std::cout << typeString << std::endl; + std::cout << valueString << std::endl; abicoder::ABICoder coder(abiCoderHeapSize); - auto [encodeStatus, encodedData] = coder.encode("bool", "true"); - solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed"); + if (!typeString.empty()) + { + auto [encodeStatus, encodedData] = coder.encode(typeString, valueString); + solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed"); + } return; } \ No newline at end of file diff --git a/test/tools/ossfuzz/abiV2Proto.proto b/test/tools/ossfuzz/abiV2Proto.proto index b6640bbe9..886ca53f7 100644 --- a/test/tools/ossfuzz/abiV2Proto.proto +++ b/test/tools/ossfuzz/abiV2Proto.proto @@ -32,10 +32,8 @@ message FixedByteType { required uint32 width = 1; } -// address, address payable -message AddressType { - required bool payable = 1; -} +// address +message AddressType {} message ValueType { oneof value_type_oneof { diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index cee5a1cf7..1fac9730a 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -1,6 +1,7 @@ #include #include +#include /// Convenience macros /// Returns a valid Solidity integer width w such that 8 <= w <= 256. @@ -315,6 +316,10 @@ pair ProtoConverter::assignChecker( m_counter += acVisitor.counted(); m_checks << assignCheckStrPair.second; + appendToIsabelleValueString( + acVisitor.isabelleValueString(), + ((m_varCounter == 1) ? Delimiter::SKIP : Delimiter::ADD) + ); // State variables cannot be assigned in contract-scope // Therefore, we buffer their assignments and @@ -333,12 +338,12 @@ std::string ProtoConverter::equalityChecksAsString() return m_checks.str(); } -std::string ProtoConverter::delimiterToString(Delimiter _delimiter) +std::string ProtoConverter::delimiterToString(Delimiter _delimiter, bool _space) { switch (_delimiter) { case Delimiter::ADD: - return ", "; + return _space ? ", " : ","; case Delimiter::SKIP: return ""; } @@ -448,7 +453,15 @@ void ProtoConverter::appendToIsabelleTypeString( Delimiter _delimiter ) { - m_isabelleTypeString << delimiterToString(_delimiter) << _typeString; + m_isabelleTypeString << delimiterToString(_delimiter, false) << _typeString; +} + +void ProtoConverter::appendToIsabelleValueString( + std::string const& _valueString, + Delimiter _delimiter +) +{ + m_isabelleValueString << delimiterToString(_delimiter, false) << _valueString; } std::string ProtoConverter::typedParametersAsString(CalleeType _calleeType) @@ -736,6 +749,15 @@ string ProtoConverter::isabelleTypeString() const return typeString; } +string ProtoConverter::isabelleValueString() const +{ + string valueString = m_isabelleValueString.str(); + if (!valueString.empty()) + return "(" + valueString + ")"; + else + return valueString; +} + string ProtoConverter::contractToString(Contract const& _input) { visit(_input); @@ -777,9 +799,9 @@ string TypeVisitor::visit(FixedByteType const& _type) return m_baseType; } -string TypeVisitor::visit(AddressType const& _type) +string TypeVisitor::visit(AddressType const&) { - m_baseType = getAddressTypeAsString(_type); + m_baseType = "address"; m_structTupleString.addTypeStringToTuple(m_baseType); return m_baseType; } @@ -890,33 +912,50 @@ string TypeVisitor::visit(StructType const& _type) } /// AssignCheckVisitor implementation +void AssignCheckVisitor::ValueStream::appendValue(string& _value) +{ + solAssert(!_value.empty(), "Abiv2 fuzzer: Empty value"); + index++; + if (index > 1) + stream << ","; + stream << _value; +} + pair AssignCheckVisitor::visit(BoolType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); + m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(IntegerType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); + m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(FixedByteType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); + string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + m_valueStream.appendValue(isabelleValue); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(AddressType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); + string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value); + m_valueStream.appendValue(isabelleValue); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(DynamicByteArrayType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); + string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + m_valueStream.appendValue(isabelleValue); DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING; return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType); } @@ -981,6 +1020,7 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) pair assignCheckBuffer; string wasVarName = m_varName; string wasParamName = m_paramName; + m_valueStream.startArray(); for (unsigned i = 0; i < length; i++) { m_varName = wasVarName + "[" + to_string(i) + "]"; @@ -991,6 +1031,7 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) if (i < length - 1) m_structCounter = wasStructCounter; } + m_valueStream.endArray(); // Since struct visitor won't be called for zero-length // arrays, struct counter will not get incremented. Therefore, @@ -1022,6 +1063,7 @@ pair AssignCheckVisitor::visit(StructType const& _type) string wasVarName = m_varName; string wasParamName = m_paramName; + m_valueStream.startStruct(); for (auto const& t: _type.t()) { m_varName = wasVarName + ".m" + to_string(i); @@ -1035,6 +1077,7 @@ pair AssignCheckVisitor::visit(StructType const& _type) assignCheckBuffer.second += assign.second; i++; } + m_valueStream.endStruct(); m_varName = wasVarName; m_paramName = wasParamName; return assignCheckBuffer; @@ -1117,11 +1160,11 @@ string ValueGetterVisitor::visit(AddressType const&) return addressValueAsString(counter()); } -string ValueGetterVisitor::visit(DynamicByteArrayType const& _type) +string ValueGetterVisitor::visit(DynamicByteArrayType const&) { return bytesArrayValueAsString( counter(), - getDataTypeOfDynBytesType(_type) == DataType::BYTES + true ); } @@ -1195,10 +1238,29 @@ std::string ValueGetterVisitor::fixedByteValueAsString(unsigned _width, unsigned std::string ValueGetterVisitor::addressValueAsString(unsigned _counter) { - // TODO: Isabelle encoder expects address literal to be exactly + return "address(" + maskUnsignedIntToHex(_counter, 40) + ")"; +} + +std::string ValueGetterVisitor::isabelleAddressValueAsString(std::string& _solAddressString) +{ + // Isabelle encoder expects address literal to be exactly // 20 bytes and a hex string. // Example: 0x0102030405060708090a0102030405060708090a - return "address(" + maskUnsignedIntToHex(_counter, 40) + ")"; + std::regex const addressPattern("address\\((.*)\\)"); + std::smatch match; + solAssert(std::regex_match(_solAddressString, match, addressPattern), "Abiv2 fuzzer: Invalid address string"); + std::string addressHex = match[1].str(); + addressHex.erase(2, 24); + return addressHex; +} + +std::string ValueGetterVisitor::isabelleBytesValueAsString(std::string& _solBytesString) +{ + std::regex const bytesPattern("hex\"(.*)\""); + std::smatch match; + solAssert(std::regex_match(_solBytesString, match, bytesPattern), "Abiv2 fuzzer: Invalid bytes string"); + std::string bytesHex = match[1].str(); + return "0x" + bytesHex; } std::string ValueGetterVisitor::variableLengthValueAsString( diff --git a/test/tools/ossfuzz/protoToAbiV2.h b/test/tools/ossfuzz/protoToAbiV2.h index 146e444a2..722dcbd58 100644 --- a/test/tools/ossfuzz/protoToAbiV2.h +++ b/test/tools/ossfuzz/protoToAbiV2.h @@ -153,6 +153,7 @@ public: ProtoConverter(ProtoConverter&&) = delete; std::string contractToString(Contract const& _input); std::string isabelleTypeString() const; + std::string isabelleValueString() const; private: enum class Delimiter { @@ -295,6 +296,13 @@ private: Delimiter _delimiter ); + /// Append @a _valueString to value string meant to be + /// passed to Isabelle coder API. + void appendToIsabelleValueString( + std::string const& _valueString, + Delimiter _delimiter + ); + /// Returns a Solidity variable declaration statement /// @param _type: string containing Solidity type of the /// variable to be declared. @@ -367,7 +375,7 @@ private: } /// Convert delimter to a comma or null string. - static std::string delimiterToString(Delimiter _delimiter); + static std::string delimiterToString(Delimiter _delimiter, bool _space = true); /// Contains the test program std::ostringstream m_output; @@ -379,6 +387,9 @@ private: std::ostringstream m_typedParamsPublic; /// Contains type string to be passed to Isabelle API std::ostringstream m_isabelleTypeString; + /// Contains values to be encoded in the format accepted + /// by the Isabelle API. + std::ostringstream m_isabelleValueString; /// Contains type stream to be used in returndata coder function /// signature std::ostringstream m_types; @@ -476,19 +487,6 @@ public: return "bytes" + std::to_string(getFixedByteWidth(_x)); } - static std::string getAddressTypeAsString(AddressType const& _x) - { - return (_x.payable() ? "address payable" : "address"); - } - - static DataType getDataTypeOfDynBytesType(DynamicByteArrayType const& _x) - { - if (_x.type() == DynamicByteArrayType::STRING) - return DataType::STRING; - else - return DataType::BYTES; - } - // Convert _counter to string and return its keccak256 hash static u256 hashUnsignedInt(unsigned _counter) { @@ -531,7 +529,13 @@ public: // this linear equation to make the number derived from // _counter approach a uniform distribution over // [0, s_maxDynArrayLength] - return (_counter + 879) * 32 % (s_maxDynArrayLength + 1); + auto v = (_counter + 879) * 32 % (s_maxDynArrayLength + 1); + /// Always return an even number because Isabelle string + /// values are formatted as hex literals + if (v % 2 == 1) + return v + 1; + else + return v; } static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x) @@ -658,10 +662,6 @@ private: { stream << ")"; } - std::string operator()() - { - return stream.str(); - } void addTypeStringToTuple(std::string& _typeString); void addArrayBracketToType(std::string& _arrayBracket); }; @@ -735,7 +735,35 @@ public: { return m_structCounter - m_structStart; } + + std::string isabelleValueString() + { + return m_valueStream.stream.str(); + } private: + struct ValueStream + { + ValueStream() = default; + unsigned index = 0; + std::ostringstream stream; + void startStruct() + { + stream << "("; + } + void endStruct() + { + stream << ")"; + } + void startArray() + { + stream << "["; + } + void endArray() + { + stream << "]"; + } + void appendValue(std::string& _value); + }; std::string indentation() { return std::string(m_indentation * 1, '\t'); @@ -764,6 +792,7 @@ private: bool m_stateVar; unsigned m_structCounter; unsigned m_structStart; + ValueStream m_valueStream; }; /// Returns a valid value (as a string) for a given type. @@ -786,6 +815,8 @@ public: solAssert(false, "ABIv2 proto fuzzer: Cannot call valuegettervisitor on complex type"); } using AbiV2ProtoVisitor::visit; + static std::string isabelleAddressValueAsString(std::string& _solAddressString); + static std::string isabelleBytesValueAsString(std::string& _solFixedBytesString); private: unsigned counter() { From c400c61fc32f514a4be0b57bda97ef576dc03a1e Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 10 Dec 2020 17:20:30 +0100 Subject: [PATCH 02/29] Fix incorrect behaviour on clang 6. --- libsolidity/formal/CHC.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index edeaa5b23..bc20f3319 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -164,11 +164,11 @@ void CHC::endVisit(ContractDefinition const& _contract) if (base != &_contract) { m_callGraph[&_contract].insert(base); - vector> const& args = baseArgs.count(base) ? baseArgs.at(base) : decltype(args){}; auto baseConstructor = base->constructor(); - if (baseConstructor && !args.empty()) + if (baseConstructor && baseArgs.count(base)) { + vector> const& args = baseArgs.at(base); auto const& params = baseConstructor->parameters(); solAssert(params.size() == args.size(), ""); for (unsigned i = 0; i < params.size(); ++i) From 4cb9a42d9ae68386fcc8d204ea7bf8ece7f24ba6 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 10 Dec 2020 17:20:49 +0100 Subject: [PATCH 03/29] Verify minimal clang version in cmake. --- cmake/EthCompilerSettings.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 313717101..066ca74d8 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -65,11 +65,8 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional GCC-specific compiler settings. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - # Check that we've got GCC 8.0 or newer. - execute_process( - COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) - if (NOT (GCC_VERSION VERSION_GREATER 8.0 OR GCC_VERSION VERSION_EQUAL 8.0)) + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 8.0 or greater.") endif () @@ -78,6 +75,11 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + # Check that we've got clang 7.0 or newer. + if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)) + message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 7.0 or greater.") + endif () + if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # Set stack size to 32MB - by default Apple's clang defines a stack size of 8MB. # Normally 16MB is enough to run all tests, but it will exceed the stack, if -DSANITIZE=address is used. From 14ea1bc1453b778ceaffd2ea89e99c8d13ae89bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 9 Dec 2020 20:38:52 +0100 Subject: [PATCH 04/29] README describing the workflow around external tests and their repositories --- test/externalTests/README.md | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 test/externalTests/README.md diff --git a/test/externalTests/README.md b/test/externalTests/README.md new file mode 100644 index 000000000..59d3778a5 --- /dev/null +++ b/test/externalTests/README.md @@ -0,0 +1,66 @@ +## Solidity external tests +This directory contains scripts for compiling some of the popular open-source projects using the +current version of the compiler and running their test suites. + +Since projects often don't use the latest compiler, we keep a fork of each of these projects +at https://github.com/solidity-external-tests/. If changes are needed to make a project work with the +latest version of the compiler, they're maintained as a branch on top if the upstream master branch. +This is especially important for testing our `breaking` branch because we can not realistically expect +external projects to be instantly compatible with a compiler version that has not been released yet. +It also isolates us from upstream changes to some degree - their changes won't affect our test suite +until we explicitly pull them. + +### Recommended workflow + +#### Adding a new external project +1. Create a fork of the upstream repository in https://github.com/solidity-external-tests/. If the + project consists of several repositories, fork them all. +2. Remove all the branches except for main one (`master`, `develop`, `main`, etc). This branch is + going to be always kept up to date with the upstream repository and should not contain any extra + commits. +3. Create two new versions of the main branch, representing versions of the compiler currently in + `develop` and `breaking`. E.g. if the latest Solidity version is 0.7.5 and the main branch of the + external project is called `master`, create `master_070` and `master_080`. This is where we will + be adding our own commits. The one corresponding to the newer Solidity version should always be + on top on the older one. E.g. if a change is needed to keep the project + compilable using Solidity 0.7.x, add it in `master_070` and rebase `master_080` on top of it. + If it is only needed for the compiler from its `breaking` branch, add it only in `master_080`. + - The fewer commits in these branches, the better. Ideally, any changes needed to make the compiler + work should be submitted upstream and the branches should just be tracking the upstream + one without any extra commits. +4. Create a script for compiling/testing the project and put it in `test/externalTests/` in the + Solidity repository. + - The script should apply workarounds necessary to make the project actually use the compiler + binary it receives as a parameter and possibly apply some generic workarounds that should + work across different versions of the upstream project. Very specific workarounds that may + easily break with every upstream change are better done as commits in the fork. +5. Add the script to `tests/externalTests.sh`. +6. Add the test to CircleCI configuration. Make sure to add both a compilation-only run and one that + also executes the test suite. If the latter takes a significant amount of time (say, more + than 15 minutes) make it run nightly rather than on every PR. + +#### Pulling upstream changes into a fork +1. Pull changes directly into the main branch in the fork. This should be straightforward thanks to + it not containing any of our customizations. +2. If the update is straightforward and looks safe, go straight to point 5. Otherwise you need to + test it first. +3. Create new branches corresponding to the two versioned ones but suffixed with `_new`. E.g. + `master_070_new` and `master_080_new`. Then rebase them so that they are on top of the updated + main branch. This may require tweaking some of the commits to apply our fixes in new places. +4. Create PRs on `deveop` and `breaking` in Solidity repo which modify the script to use the new + branches instead of `master_070`/`master_080`. Tweak the new branches until external tests + in CI pass in the PRs. +5. Discard the PRs and move the original branches to the place where the `_new` ones are and remove + the `_new` branches. + +#### Changes needed after a breaking release of the compiler +When a breaking version of the compiler gets released and becomes the most recent release, the scripts +and the branches in the forks need to be updated: +- In each fork create a branch corresponding to the new brekaing version. E.g. if the current + branches are `master_070` and `master_080` the new one should be called `master_090`. +- Leave the oldest (i.e. `master_070`) branch as is. We will not be updating it any more but there is no + need to remove it. +- Update scripts on `develop` to now refer to the branch that used to be breaking (i.e. `master_080`) + and on `breaking` to refer to the newly added branch (i.e. `master_090`). + - Take care not to overwrite these changes when merging `develop` into breaking. Each branch + should always use the branches from the external repos that correspond to it. From 12418c533bcd71bec6fe0ba8f516b09b6ebbe905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 10 Dec 2020 17:31:22 +0100 Subject: [PATCH 05/29] fixup! README describing the workflow around external tests and their repositories --- test/externalTests/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/externalTests/README.md b/test/externalTests/README.md index 59d3778a5..870253810 100644 --- a/test/externalTests/README.md +++ b/test/externalTests/README.md @@ -2,12 +2,12 @@ This directory contains scripts for compiling some of the popular open-source projects using the current version of the compiler and running their test suites. -Since projects often don't use the latest compiler, we keep a fork of each of these projects +Since projects often do not use the latest compiler, we keep a fork of each of these projects at https://github.com/solidity-external-tests/. If changes are needed to make a project work with the -latest version of the compiler, they're maintained as a branch on top if the upstream master branch. +latest version of the compiler, they are maintained as a branch on top of the upstream master branch. This is especially important for testing our `breaking` branch because we can not realistically expect external projects to be instantly compatible with a compiler version that has not been released yet. -It also isolates us from upstream changes to some degree - their changes won't affect our test suite +It also isolates us from upstream changes to some degree - their changes will not affect our test suite until we explicitly pull them. ### Recommended workflow @@ -22,7 +22,7 @@ until we explicitly pull them. `develop` and `breaking`. E.g. if the latest Solidity version is 0.7.5 and the main branch of the external project is called `master`, create `master_070` and `master_080`. This is where we will be adding our own commits. The one corresponding to the newer Solidity version should always be - on top on the older one. E.g. if a change is needed to keep the project + rebased on top of the older one. E.g. if a change is needed to keep the project compilable using Solidity 0.7.x, add it in `master_070` and rebase `master_080` on top of it. If it is only needed for the compiler from its `breaking` branch, add it only in `master_080`. - The fewer commits in these branches, the better. Ideally, any changes needed to make the compiler @@ -47,7 +47,7 @@ until we explicitly pull them. 3. Create new branches corresponding to the two versioned ones but suffixed with `_new`. E.g. `master_070_new` and `master_080_new`. Then rebase them so that they are on top of the updated main branch. This may require tweaking some of the commits to apply our fixes in new places. -4. Create PRs on `deveop` and `breaking` in Solidity repo which modify the script to use the new +4. Create PRs on `develop` and `breaking` in Solidity repo which modify the script to use the new branches instead of `master_070`/`master_080`. Tweak the new branches until external tests in CI pass in the PRs. 5. Discard the PRs and move the original branches to the place where the `_new` ones are and remove @@ -56,7 +56,7 @@ until we explicitly pull them. #### Changes needed after a breaking release of the compiler When a breaking version of the compiler gets released and becomes the most recent release, the scripts and the branches in the forks need to be updated: -- In each fork create a branch corresponding to the new brekaing version. E.g. if the current +- In each fork create a branch corresponding to the new breaking version. E.g. if the current branches are `master_070` and `master_080` the new one should be called `master_090`. - Leave the oldest (i.e. `master_070`) branch as is. We will not be updating it any more but there is no need to remove it. From 747e1709ff4f9d695097fbec68ad1461aebb68fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Thu, 10 Dec 2020 19:52:53 +0100 Subject: [PATCH 06/29] fixup! README describing the workflow around external tests and their repositories --- test/externalTests/README.md | 104 ++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 39 deletions(-) diff --git a/test/externalTests/README.md b/test/externalTests/README.md index 870253810..a6c160846 100644 --- a/test/externalTests/README.md +++ b/test/externalTests/README.md @@ -7,8 +7,8 @@ at https://github.com/solidity-external-tests/. If changes are needed to make a latest version of the compiler, they are maintained as a branch on top of the upstream master branch. This is especially important for testing our `breaking` branch because we can not realistically expect external projects to be instantly compatible with a compiler version that has not been released yet. -It also isolates us from upstream changes to some degree - their changes will not affect our test suite -until we explicitly pull them. +Applying necessary changes ourselves gives us confidence that breaking changes are sane and that +these projects *can* be upgraded at all. ### Recommended workflow @@ -18,49 +18,75 @@ until we explicitly pull them. 2. Remove all the branches except for main one (`master`, `develop`, `main`, etc). This branch is going to be always kept up to date with the upstream repository and should not contain any extra commits. -3. Create two new versions of the main branch, representing versions of the compiler currently in - `develop` and `breaking`. E.g. if the latest Solidity version is 0.7.5 and the main branch of the - external project is called `master`, create `master_070` and `master_080`. This is where we will - be adding our own commits. The one corresponding to the newer Solidity version should always be - rebased on top of the older one. E.g. if a change is needed to keep the project - compilable using Solidity 0.7.x, add it in `master_070` and rebase `master_080` on top of it. - If it is only needed for the compiler from its `breaking` branch, add it only in `master_080`. - - The fewer commits in these branches, the better. Ideally, any changes needed to make the compiler - work should be submitted upstream and the branches should just be tracking the upstream - one without any extra commits. + - If the project is not up to date with the latest compiler version but has a branch that is, + try to use that branch instead. +3. Create a new branch named after the main branch and the compiler version from our `develop` + branch. E.g. if the latest Solidity version is 0.7.5 and the main branch of the external project + is called `master`, create `master_070`. This is where we will be adding our own commits. 4. Create a script for compiling/testing the project and put it in `test/externalTests/` in the Solidity repository. - The script should apply workarounds necessary to make the project actually use the compiler - binary it receives as a parameter and possibly apply some generic workarounds that should - work across different versions of the upstream project. Very specific workarounds that may - easily break with every upstream change are better done as commits in the fork. -5. Add the script to `tests/externalTests.sh`. -6. Add the test to CircleCI configuration. Make sure to add both a compilation-only run and one that - also executes the test suite. If the latter takes a significant amount of time (say, more - than 15 minutes) make it run nightly rather than on every PR. + binary it receives as a parameter and possibly add generic workarounds that should + work across different versions of the upstream project. + - Very specific workarounds that may easily break with every upstream change are better done as + commits in the newly added branch in the fork instead. +5. List the script in `test/externalTests.sh`. +6. Add the script to CircleCI configuration. Make sure to add both a compilation-only run and one that + also executes the test suite. If the latter takes a significant amount of time (say, more than + 15 minutes) make it run nightly rather than on every PR. +7. Make sure that tests pass both on `develop` and on `breaking`. If the compiler from `breaking` + branch will not work without additional changes, add another branch, called after it in turn, + and add necessary workarounds there. Continuing the example above, the new branch would be + called `master_080` and should be rebased on top of `master_070`. + - The fewer commits in these branches, the better. Ideally, any changes needed to make the compiler + work should be submitted upstream and our branches should just be tracking the main upstream + branch without any extra commits. + +#### Updating external projects for a PR that introduces breaking changes in the compiler +If a PR to our `breaking` branch introduces changes that will make an external project no longer +compile or pass its tests, the fork needs to be modified: +- If a branch specific to the compiler version from `breaking` does not exist yet: + 1. Create the branch. It should be based on the version-specific branch used on `develop`. + 2. Make your PR modify the project script in `test/externalScripts/` to use the new branch. + 3. You are free to add any changes you need in the new branch since it will not interfere with + tests on `breaking`. + 4. Work on your PR until it is approved and merged into `breaking`. +- If the branch already exists and our CI depends on it: + 1. If the external project after your changes can still work with `breaking` even without your PR or + if you know that the PR is straightforward and will be merged immediately without interfering + with tests on `breaking` for a significant amount of time, you can just push your modifications + to the branch directly and skip straight to steps 4. and 6. + 2. Create a PR in the fork, targeting the existing version-specific branch. + 3. In your PR to `breaking`, modify the corresponding script in `test/externalScripts/` to + use the branch from your PR in the fork. + 4. Work on your PR until it is approved and ready to merge. + 5. Merge the PR in the fork. + 6. Discard your changes to the script and merge your PR into `breaking`. #### Pulling upstream changes into a fork 1. Pull changes directly into the main branch in the fork. This should be straightforward thanks to it not containing any of our customizations. -2. If the update is straightforward and looks safe, go straight to point 5. Otherwise you need to - test it first. -3. Create new branches corresponding to the two versioned ones but suffixed with `_new`. E.g. - `master_070_new` and `master_080_new`. Then rebase them so that they are on top of the updated - main branch. This may require tweaking some of the commits to apply our fixes in new places. -4. Create PRs on `develop` and `breaking` in Solidity repo which modify the script to use the new - branches instead of `master_070`/`master_080`. Tweak the new branches until external tests - in CI pass in the PRs. -5. Discard the PRs and move the original branches to the place where the `_new` ones are and remove - the `_new` branches. +2. If the project has been updated to a newer Solidity version, abandon the current version-specific + branch used on `develop` (but do not delete it) and create a new one corresponding to the newer + version. Then update project script in `test/externalTests/` to use the new branch. E.g. if `develop` uses + `master_050` and the project has been updated to use Solidity 0.7.3, create `master_070`. +3. Otherwise, rebase the current version-specific branch on the main branch of the fork. This may require + tweaking some of the commits to apply our fixes in new places. +4. If we have a separate branch for `breaking`, rebase it on top of the one used on `develop`. + +The above is the workflow to use when the update is straightforward and looks safe. In that case it is +fine to just modify the branches directly. If this is not the case, it is recommended to first perform the +operation on copies of these version-specific branches and test them by creating PRs on `develop` and +`breaking` to see if tests pass. The PRs should just modify project scripts in `test/externalScripts/` +to use the updated copies of the branches and can be discarded aferwards without being merged. #### Changes needed after a breaking release of the compiler -When a breaking version of the compiler gets released and becomes the most recent release, the scripts -and the branches in the forks need to be updated: -- In each fork create a branch corresponding to the new breaking version. E.g. if the current - branches are `master_070` and `master_080` the new one should be called `master_090`. -- Leave the oldest (i.e. `master_070`) branch as is. We will not be updating it any more but there is no - need to remove it. -- Update scripts on `develop` to now refer to the branch that used to be breaking (i.e. `master_080`) - and on `breaking` to refer to the newly added branch (i.e. `master_090`). - - Take care not to overwrite these changes when merging `develop` into breaking. Each branch - should always use the branches from the external repos that correspond to it. +When a non-backwards-compatible version becomes the most recent release, `breaking` branch +gets merged into `develop` which automatically results in a switch to the newer version-specific +branches if they exist. If no changes on our part were necessary, it is completely fine to keep using +e.g. the `master_060` of an external project in in Solidity 0.8.x. + +Since each project is handled separately, this approach may result in a mix of version-specific branches +between different external projects. For example, in one project we could could have `master_050` on +both `develop` and `breaking` and in another `breaking` could use `master_080` while `develop` still +uses `master_060`. From 7764ee8d86c160c25718e365722c70d31c655eb1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 10 Dec 2020 18:16:45 +0100 Subject: [PATCH 07/29] Fix copying byte arrays from storage to storage. --- libsolidity/codegen/YulUtilFunctions.cpp | 16 ++++++++---- .../copying/bytes_storage_to_storage.sol | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index f177d65fc..db92a7a0a 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1633,8 +1633,9 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy let oldLen := (sload(slot)) + let srcOffset := 0 - src := add(src, 0x20) + srcOffset := 0x20 // This is not needed in all branches. @@ -1652,14 +1653,16 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy switch gt(newLen, 31) case 1 { let loopEnd := and(newLen, not(0x1f)) + src := (src) let dstPtr := dstDataArea let i := 0 - for { } lt(i, loopEnd) { i := add(i, 32) } { - sstore(dstPtr, (add(src, i))) + for { } lt(i, loopEnd) { i := add(i, 0x20) } { + sstore(dstPtr, (add(src, srcOffset))) dstPtr := add(dstPtr, 1) + srcOffset := add(srcOffset, ) } if lt(loopEnd, newLen) { - let lastValue := (add(src, i)) + let lastValue := (add(src, srcOffset)) sstore(dstPtr, (lastValue, and(newLen, 0x1f))) } sstore(slot, add(mul(newLen, 2), 1)) @@ -1667,7 +1670,7 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy default { let value := 0 if newLen { - value := (src) + value := (add(src, srcOffset)) } sstore(slot, (value, newLen)) } @@ -1683,7 +1686,10 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy templ("panic", panicFunction()); templ("byteArrayLength", extractByteArrayLengthFunction()); templ("dstDataLocation", arrayDataAreaFunction(_toType)); + if (fromStorage) + templ("srcDataLocation", arrayDataAreaFunction(_fromType)); templ("clearStorageRange", clearStorageRangeFunction(*_toType.baseType())); + templ("srcIncrement", to_string(fromStorage ? 1 : 0x20)); templ("read", fromStorage ? "sload" : fromCalldata ? "calldataload" : "mload"); templ("maskBytes", maskBytesFunctionDynamic()); templ("byteArrayCombineShort", shortByteArrayEncodeUsedAreaSetLengthFunction()); diff --git a/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol new file mode 100644 index 000000000..aadd82cd9 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/bytes_storage_to_storage.sol @@ -0,0 +1,26 @@ +contract c { + bytes a; + bytes b; + function f(uint len) public returns (bytes memory) { + bytes memory x = new bytes(len); + for (uint i = 0; i < len; i++) + x[i] = byte(uint8(i)); + a = x; + for (uint i = 0; i < len; i++) + assert(a[i] == x[i]); + b = a; + for (uint i = 0; i < len; i++) + assert(b[i] == x[i]); + return b; + } +} +// ==== +// compileViaYul: also +// ---- +// f(uint256): 0 -> 0x20, 0x00 +// f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00 +// f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671 +// f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000 +// f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992 +// f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000 +// f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968 From bd641a5206c211ee63b02232e87a4f8ab53d1568 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 8 Dec 2020 20:06:10 +0000 Subject: [PATCH 08/29] Enable more C++ compiler warnings --- cmake/EthCompilerSettings.cmake | 9 ++++++++ liblangutil/Token.cpp | 3 +++ libsolidity/analysis/GlobalContext.cpp | 4 ++++ libsolidity/formal/SymbolicVariables.cpp | 2 +- libsolutil/UTF8.cpp | 4 ++-- libyul/optimiser/FunctionCallFinder.cpp | 2 +- libyul/optimiser/StackToMemoryMover.h | 2 +- solc/CommandLineInterface.cpp | 10 +++++++++ test/Common.cpp | 5 +++++ test/boostTest.cpp | 4 ++++ test/evmc/CMakeLists.txt | 2 +- test/libsolidity/SemVerMatcher.cpp | 5 +++++ test/libsolidity/util/TestFileParserTests.cpp | 5 +++++ test/libsolutil/SwarmHash.cpp | 5 +++++ test/tools/IsolTestOptions.cpp | 5 +++++ test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp | 2 +- test/tools/ossfuzz/CMakeLists.txt | 21 +++++++++---------- .../SolidityCustomMutatorInterface.cpp | 6 ++---- test/tools/ossfuzz/SolidityGenerator.cpp | 2 +- test/tools/ossfuzz/SolidityGenerator.h | 2 +- test/tools/ossfuzz/abiV2FuzzerCommon.cpp | 2 +- test/tools/ossfuzz/const_opt_ossfuzz.cpp | 5 ++++- test/tools/ossfuzz/solc_noopt_ossfuzz.cpp | 3 +++ test/tools/ossfuzz/solc_opt_ossfuzz.cpp | 3 +++ .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 3 +++ test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 3 +++ test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 3 +++ 27 files changed, 96 insertions(+), 26 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 066ca74d8..adbc3a661 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -48,6 +48,7 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA add_compile_options(-Wextra) add_compile_options(-Werror) add_compile_options(-pedantic) + add_compile_options(-Wmissing-declarations) add_compile_options(-Wno-unknown-pragmas) add_compile_options(-Wimplicit-fallthrough) add_compile_options(-Wsign-conversion) @@ -56,6 +57,14 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA eth_add_cxx_compiler_flag_if_supported( $<$:-Wextra-semi> ) + eth_add_cxx_compiler_flag_if_supported(-Wfinal-dtor-non-final-class) + eth_add_cxx_compiler_flag_if_supported(-Wnewline-eof) + eth_add_cxx_compiler_flag_if_supported(-Wsuggest-destructor-override) + eth_add_cxx_compiler_flag_if_supported(-Wunreachable-code-break) + eth_add_cxx_compiler_flag_if_supported(-Wduplicated-cond) + eth_add_cxx_compiler_flag_if_supported(-Wduplicate-enum) + eth_add_cxx_compiler_flag_if_supported(-Wlogical-op) + eth_add_cxx_compiler_flag_if_supported(-Wno-unknown-attributes) # Configuration-specific compiler settings. set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -DETH_DEBUG") diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index bbcfe1590..28180514a 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -126,6 +126,8 @@ int precedence(Token tok) } #undef T +namespace +{ int parseSize(string::const_iterator _begin, string::const_iterator _end) { try @@ -138,6 +140,7 @@ int parseSize(string::const_iterator _begin, string::const_iterator _end) return -1; } } +} static Token keywordByName(string const& _name) { diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index dee7e8220..aef68fe25 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -34,6 +34,8 @@ using namespace std; namespace solidity::frontend { +namespace +{ /// Magic variables get negative ids for easy differentiation int magicVariableToID(std::string const& _name) { @@ -113,6 +115,8 @@ inline vector> constructMagicVariable }; } +} + GlobalContext::GlobalContext(): m_magicVariables{constructMagicVariables()} { } diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 5c23fbf66..8f78495a9 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -399,4 +399,4 @@ smtutil::Expression SymbolicStructVariable::assignAllMembers(vectorname())); return currentValue(); -} \ No newline at end of file +} diff --git a/libsolutil/UTF8.cpp b/libsolutil/UTF8.cpp index 4acf7a8ea..baeda14b0 100644 --- a/libsolutil/UTF8.cpp +++ b/libsolutil/UTF8.cpp @@ -76,8 +76,6 @@ bool isWellFormed(unsigned char byte1, unsigned char byte2) return false; } -} - bool validateUTF8(unsigned char const* _input, size_t _length, size_t& _invalidPosition) { bool valid = true; @@ -134,6 +132,8 @@ bool validateUTF8(unsigned char const* _input, size_t _length, size_t& _invalidP return false; } +} + bool validateUTF8(std::string const& _input, size_t& _invalidPosition) { return validateUTF8(reinterpret_cast(_input.c_str()), _input.length(), _invalidPosition); diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 4bc1998b1..b8f206440 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -36,4 +36,4 @@ void FunctionCallFinder::operator()(FunctionCall& _functionCall) ASTModifier::operator()(_functionCall); if (_functionCall.functionName.name == m_functionName) m_calls.emplace_back(&_functionCall); -} \ No newline at end of file +} diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index 5cbc5a5a0..2ec831946 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -129,4 +129,4 @@ private: NameDispenser& m_nameDispenser; }; -} \ No newline at end of file +} diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index b74cc224f..238cd6541 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -92,6 +92,9 @@ namespace solidity::frontend bool g_hasOutput = false; +namespace +{ + std::ostream& sout() { g_hasOutput = true; @@ -105,6 +108,8 @@ std::ostream& serr(bool _used = true) return cerr; } +} + #define cout #define cerr @@ -329,6 +334,9 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) return false; } +namespace +{ + bool checkMutuallyExclusive(boost::program_options::variables_map const& args, std::string const& _optionA, std::string const& _optionB) { if (args.count(_optionA) && args.count(_optionB)) @@ -340,6 +348,8 @@ bool checkMutuallyExclusive(boost::program_options::variables_map const& args, s return true; } +} + void CommandLineInterface::handleBinary(string const& _contract) { if (m_args.count(g_argBinary)) diff --git a/test/Common.cpp b/test/Common.cpp index 5e7059013..4be957a03 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -30,6 +30,9 @@ namespace po = boost::program_options; namespace solidity::test { +namespace +{ + /// If non-empty returns the value of the env. variable ETH_TEST_PATH, otherwise /// it tries to find a path that contains the directories "libsolidity/syntaxTests" /// and returns it if found. @@ -84,6 +87,8 @@ std::string envOrDefaultPath(std::string const& env_name, std::string const& lib return {}; } +} + CommonOptions::CommonOptions(std::string _caption): options(_caption, po::options_description::m_default_line_length, diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 81aae19ab..36620337e 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -148,6 +148,10 @@ void initializeOptions() } } +// TODO: Prototype -- why isn't this declared in the boost headers? +// TODO: replace this with a (global) fixture. +test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ); + test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) { master_test_suite_t& master = framework::master_test_suite(); diff --git a/test/evmc/CMakeLists.txt b/test/evmc/CMakeLists.txt index bd64e8625..b49b85a29 100644 --- a/test/evmc/CMakeLists.txt +++ b/test/evmc/CMakeLists.txt @@ -19,4 +19,4 @@ target_sources(evmc INTERFACE ${PROJECT_SOURCE_DIR}/test/evmc/utils.h ) target_include_directories(evmc INTERFACE ${PROJECT_SOURCE_DIR}/test/) -target_link_libraries(evmc INTERFACE evmc_loader) \ No newline at end of file +target_link_libraries(evmc INTERFACE evmc_loader) diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index a3e1661ef..5337c844a 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -38,6 +38,9 @@ namespace solidity::frontend::test BOOST_AUTO_TEST_SUITE(SemVerMatcher) +namespace +{ + SemVerMatchExpression parseExpression(string const& _input) { Scanner scanner{CharStream(_input, "")}; @@ -62,6 +65,8 @@ SemVerMatchExpression parseExpression(string const& _input) return expression; } +} + BOOST_AUTO_TEST_CASE(positive_range) { // Positive range tests diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index cf83d3029..242b721b9 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -39,6 +39,9 @@ namespace solidity::frontend::test using fmt = ExecutionFramework; using Mode = FunctionCall::DisplayMode; +namespace +{ + vector parse(string const& _source) { istringstream stream{_source, ios_base::out}; @@ -86,6 +89,8 @@ void testFunctionCall( BOOST_REQUIRE_EQUAL(_call.kind == FunctionCall::Kind::Library, _isLibrary); } +} + BOOST_AUTO_TEST_SUITE(TestFileParserTest) BOOST_AUTO_TEST_CASE(smoke_test) diff --git a/test/libsolutil/SwarmHash.cpp b/test/libsolutil/SwarmHash.cpp index 3b13cd382..5d0c22a80 100644 --- a/test/libsolutil/SwarmHash.cpp +++ b/test/libsolutil/SwarmHash.cpp @@ -34,6 +34,9 @@ namespace solidity::util::test BOOST_AUTO_TEST_SUITE(SwarmHash, *boost::unit_test::label("nooptions")) +namespace +{ + string bzzr0HashHex(string const& _input) { return toHex(bzzr0Hash(_input).asBytes()); @@ -52,6 +55,8 @@ bytes sequence(size_t _length) return data; } +} + BOOST_AUTO_TEST_CASE(test_zeros) { BOOST_CHECK_EQUAL(bzzr0HashHex(string()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce")); diff --git a/test/tools/IsolTestOptions.cpp b/test/tools/IsolTestOptions.cpp index 943832677..763a0b3b7 100644 --- a/test/tools/IsolTestOptions.cpp +++ b/test/tools/IsolTestOptions.cpp @@ -35,6 +35,9 @@ namespace po = boost::program_options; namespace solidity::test { +namespace +{ + auto const description = R"(isoltest, tool for interactively managing test contracts. Usage: isoltest [Options] Interactively validates test contracts. @@ -51,6 +54,8 @@ std::string editorPath() return std::string{}; } +} + IsolTestOptions::IsolTestOptions(std::string* _editor): CommonOptions(description) { diff --git a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp index 4e28c444b..87b7fd913 100644 --- a/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp +++ b/test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp @@ -52,4 +52,4 @@ DEFINE_PROTO_FUZZER(Contract const& _contract) solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed"); } return; -} \ No newline at end of file +} diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 0e1238ee8..3d205722b 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -10,14 +10,13 @@ add_dependencies(ossfuzz strictasm_assembly_ossfuzz ) - if (OSSFUZZ) add_custom_target(ossfuzz_proto) add_dependencies(ossfuzz_proto - sol_proto_ossfuzz - yul_proto_ossfuzz - yul_proto_diff_ossfuzz - yul_proto_diff_custom_mutate_ossfuzz + sol_proto_ossfuzz + yul_proto_ossfuzz + yul_proto_diff_ossfuzz + yul_proto_diff_custom_mutate_ossfuzz ) add_custom_target(ossfuzz_abiv2) @@ -85,7 +84,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc) target_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator) @@ -96,7 +95,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) add_executable(yul_proto_diff_custom_mutate_ossfuzz yulProto_diff_ossfuzz.cpp @@ -113,7 +112,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) add_executable(abiv2_proto_ossfuzz ../../EVMHost.cpp @@ -133,7 +132,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) add_executable(abiv2_isabelle_ossfuzz ../../EVMHost.cpp @@ -155,7 +154,7 @@ if (OSSFUZZ) gmp ) set_target_properties(abiv2_isabelle_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) add_executable(sol_proto_ossfuzz solProtoFuzzer.cpp @@ -175,7 +174,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(sol_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override) else() add_library(solc_opt_ossfuzz solc_opt_ossfuzz.cpp diff --git a/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp b/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp index ac56860b9..16c71f970 100644 --- a/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp +++ b/test/tools/ossfuzz/SolidityCustomMutatorInterface.cpp @@ -24,10 +24,9 @@ using namespace std; using namespace solidity::test::fuzzer; -namespace -{ -/// Forward declare libFuzzer's default mutator definition +// Prototype as we can't use the FuzzerInterface.h header. extern "C" size_t LLVMFuzzerMutate(uint8_t* _data, size_t _size, size_t _maxSize); +extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* _data, size_t size, size_t _maxSize, unsigned int seed); /// Define Solidity's custom mutator by implementing libFuzzer's /// custom mutator external interface. @@ -42,7 +41,6 @@ extern "C" size_t LLVMFuzzerCustomMutator( return LLVMFuzzerMutate(_data, _size, _maxSize); return SolidityCustomMutatorInterface{_data, _size, _maxSize, _seed}.generate(); } -} SolidityCustomMutatorInterface::SolidityCustomMutatorInterface( uint8_t* _data, diff --git a/test/tools/ossfuzz/SolidityGenerator.cpp b/test/tools/ossfuzz/SolidityGenerator.cpp index f9c43ef66..6e9198b87 100644 --- a/test/tools/ossfuzz/SolidityGenerator.cpp +++ b/test/tools/ossfuzz/SolidityGenerator.cpp @@ -32,4 +32,4 @@ string SolidityGenerator::generateTestProgram() return Whiskers(R"(pragma ;)") ("directive", "solidity >= 0.0.0") .render(); -} \ No newline at end of file +} diff --git a/test/tools/ossfuzz/SolidityGenerator.h b/test/tools/ossfuzz/SolidityGenerator.h index 5b7abce04..55c3c1f3a 100644 --- a/test/tools/ossfuzz/SolidityGenerator.h +++ b/test/tools/ossfuzz/SolidityGenerator.h @@ -39,4 +39,4 @@ private: /// Random number generator RandomEngine const m_rand; }; -} \ No newline at end of file +} diff --git a/test/tools/ossfuzz/abiV2FuzzerCommon.cpp b/test/tools/ossfuzz/abiV2FuzzerCommon.cpp index 9e506b7d7..ac354c029 100644 --- a/test/tools/ossfuzz/abiV2FuzzerCommon.cpp +++ b/test/tools/ossfuzz/abiV2FuzzerCommon.cpp @@ -79,4 +79,4 @@ evmc::result AbiV2Utility::deployContract(EVMHost& _hostContext, bytes const& _c evmc_message message = initializeMessage(_code); message.kind = EVMC_CREATE; return _hostContext.call(message); -} \ No newline at end of file +} diff --git a/test/tools/ossfuzz/const_opt_ossfuzz.cpp b/test/tools/ossfuzz/const_opt_ossfuzz.cpp index 60b1febbc..0b799c956 100644 --- a/test/tools/ossfuzz/const_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/const_opt_ossfuzz.cpp @@ -20,6 +20,9 @@ using namespace std; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 250) @@ -28,4 +31,4 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) FuzzerUtil::testConstantOptimizer(input, /*quiet=*/true); } return 0; -} \ No newline at end of file +} diff --git a/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp b/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp index 4261f60d3..8d9e098ce 100644 --- a/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp @@ -25,6 +25,9 @@ using namespace solidity::frontend::test; using namespace std; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 600) diff --git a/test/tools/ossfuzz/solc_opt_ossfuzz.cpp b/test/tools/ossfuzz/solc_opt_ossfuzz.cpp index 5cd8e3460..78a0772bf 100644 --- a/test/tools/ossfuzz/solc_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_opt_ossfuzz.cpp @@ -25,6 +25,9 @@ using namespace solidity::frontend::test; using namespace std; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 600) diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 458bde745..e25de4f05 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -24,6 +24,9 @@ using namespace solidity; using namespace solidity::yul; using namespace std; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size > 600) diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index bd6d249b3..7372e17f0 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -44,6 +44,9 @@ using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::yul::test::yul_fuzzer; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size > 600) diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 646e6ea6a..b1aa9a21f 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -24,6 +24,9 @@ using namespace solidity::util; using namespace solidity::yul; using namespace std; +// Prototype as we can't use the FuzzerInterface.h header. +extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size); + extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size > 600) From 9bd4a1095ea7e2083de2de00f3ff620188edc7a3 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Thu, 10 Dec 2020 18:43:48 +0100 Subject: [PATCH 09/29] Ensure empty arrays are not visited and fix formatting issues --- test/tools/ossfuzz/protoToAbiV2.cpp | 45 ++++++++++++++++++++--------- test/tools/ossfuzz/protoToAbiV2.h | 8 +++++ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/test/tools/ossfuzz/protoToAbiV2.cpp b/test/tools/ossfuzz/protoToAbiV2.cpp index 1fac9730a..4e5b2081a 100644 --- a/test/tools/ossfuzz/protoToAbiV2.cpp +++ b/test/tools/ossfuzz/protoToAbiV2.cpp @@ -924,38 +924,49 @@ void AssignCheckVisitor::ValueStream::appendValue(string& _value) pair AssignCheckVisitor::visit(BoolType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); - m_valueStream.appendValue(value); + if (!m_forcedVisit) + m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(IntegerType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); - m_valueStream.appendValue(value); + if (!m_forcedVisit) + m_valueStream.appendValue(value); return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(FixedByteType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); - string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); - m_valueStream.appendValue(isabelleValue); + if (!m_forcedVisit) + { + string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + m_valueStream.appendValue(isabelleValue); + } return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(AddressType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); - string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value); - m_valueStream.appendValue(isabelleValue); + if (!m_forcedVisit) + { + string isabelleValue = ValueGetterVisitor{}.isabelleAddressValueAsString(value); + m_valueStream.appendValue(isabelleValue); + } return assignAndCheckStringPair(m_varName, m_paramName, value, value, DataType::VALUE); } pair AssignCheckVisitor::visit(DynamicByteArrayType const& _type) { string value = ValueGetterVisitor(counter()).visit(_type); - string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); - m_valueStream.appendValue(isabelleValue); + if (!m_forcedVisit) + { + string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value); + m_valueStream.appendValue(isabelleValue); + } DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING; return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType); } @@ -1020,7 +1031,8 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) pair assignCheckBuffer; string wasVarName = m_varName; string wasParamName = m_paramName; - m_valueStream.startArray(); + if (!m_forcedVisit) + m_valueStream.startArray(); for (unsigned i = 0; i < length; i++) { m_varName = wasVarName + "[" + to_string(i) + "]"; @@ -1031,13 +1043,18 @@ pair AssignCheckVisitor::visit(ArrayType const& _type) if (i < length - 1) m_structCounter = wasStructCounter; } - m_valueStream.endArray(); - // Since struct visitor won't be called for zero-length // arrays, struct counter will not get incremented. Therefore, // we need to manually force a recursive struct visit. if (length == 0 && TypeVisitor().arrayOfStruct(_type)) + { + bool previousState = m_forcedVisit; + m_forcedVisit = true; visit(_type.t()); + m_forcedVisit = previousState; + } + if (!m_forcedVisit) + m_valueStream.endArray(); m_varName = wasVarName; m_paramName = wasParamName; @@ -1063,7 +1080,8 @@ pair AssignCheckVisitor::visit(StructType const& _type) string wasVarName = m_varName; string wasParamName = m_paramName; - m_valueStream.startStruct(); + if (!m_forcedVisit) + m_valueStream.startStruct(); for (auto const& t: _type.t()) { m_varName = wasVarName + ".m" + to_string(i); @@ -1077,7 +1095,8 @@ pair AssignCheckVisitor::visit(StructType const& _type) assignCheckBuffer.second += assign.second; i++; } - m_valueStream.endStruct(); + if (!m_forcedVisit) + m_valueStream.endStruct(); m_varName = wasVarName; m_paramName = wasParamName; return assignCheckBuffer; diff --git a/test/tools/ossfuzz/protoToAbiV2.h b/test/tools/ossfuzz/protoToAbiV2.h index 722dcbd58..4d7421de4 100644 --- a/test/tools/ossfuzz/protoToAbiV2.h +++ b/test/tools/ossfuzz/protoToAbiV2.h @@ -748,6 +748,9 @@ private: std::ostringstream stream; void startStruct() { + if (index >= 1) + stream << ","; + index = 0; stream << "("; } void endStruct() @@ -756,11 +759,15 @@ private: } void startArray() { + if (index >= 1) + stream << ","; + index = 0; stream << "["; } void endArray() { stream << "]"; + index++; } void appendValue(std::string& _value); }; @@ -793,6 +800,7 @@ private: unsigned m_structCounter; unsigned m_structStart; ValueStream m_valueStream; + bool m_forcedVisit = false; }; /// Returns a valid value (as a string) for a given type. From ff7e45f41799ccc399ff0e4515d0cfa0dcfe00cd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 8 Jul 2020 18:23:44 +0100 Subject: [PATCH 10/29] Add test cases for assigning builtins/bound functions to function types --- .../syntaxTests/functionTypes/assign_bound.sol | 15 +++++++++++++++ .../syntaxTests/functionTypes/assign_builtin.sol | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 test/libsolidity/syntaxTests/functionTypes/assign_bound.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol diff --git a/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol b/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol new file mode 100644 index 000000000..eac080e53 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol @@ -0,0 +1,15 @@ +library L { + function foo(uint256 a, uint256 b) internal pure returns (uint256) { + return a + b; + } +} +contract C { + using L for uint256; + + function bar() public { + uint256 x; + function (uint256, uint256) internal pure returns (uint256) ptr = x.foo; + } +} +// ---- +// TypeError 9574: (209-280): Type function (uint256,uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). diff --git a/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol b/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol new file mode 100644 index 000000000..0fa43aa76 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + function (uint) view returns (bytes32) _blockhash = blockhash; + } +} +// ---- +// TypeError 9574: (42-103): Type function (uint256) view returns (bytes32) is not implicitly convertible to expected type function (uint256) view returns (bytes32). From fa37e69c2501eb816b9c5d98c7ad68c915e2dfcf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 23 Sep 2020 17:55:52 +0100 Subject: [PATCH 11/29] Improved error messages when converting to/from builtin functions --- libsolidity/analysis/TypeChecker.cpp | 5 ++++- libsolidity/ast/Types.cpp | 7 +++++++ ...all_to_v2_library_function_pointer_accepting_struct.sol | 2 +- .../syntaxTests/events/event_library_function.sol | 6 +++--- .../libsolidity/syntaxTests/functionTypes/assign_bound.sol | 2 +- .../syntaxTests/functionTypes/assign_builtin.sol | 2 +- ...external_library_function_to_external_function_type.sol | 4 ++-- .../function_type_variable_external_internal.sol | 2 +- .../nameAndTypeResolution/262_bound_function_in_var.sol | 2 +- .../members/assign_function_via_base_name_to_var.sol | 4 ++-- .../members/assign_function_via_contract_name_to_var.sol | 4 ++-- 11 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3f50f915b..fc6e8a5b5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2171,7 +2171,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks( for (size_t i = 0; i < paramArgMap.size(); ++i) { solAssert(!!paramArgMap[i], "unmapped parameter"); - if (!type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) + BoolResult result = type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i]); + if (!result) { auto [errorId, description] = [&]() -> tuple { string msg = @@ -2181,6 +2182,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks( " to " + parameterTypes[i]->toString() + " requested."; + if (!result.message().empty()) + msg += " " + result.message(); if ( _functionType->kind() == FunctionType::Kind::BareCall || _functionType->kind() == FunctionType::Kind::BareCallCode || diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f883496d7..ed3686b36 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3111,6 +3111,13 @@ BoolResult FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const FunctionType const& convertTo = dynamic_cast(_convertTo); + // These two checks are duplicated in equalExcludingStateMutability, but are added here for error reporting. + if (convertTo.bound() != bound()) + return BoolResult::err("Bound functions can not be converted to non-bound functions."); + + if (convertTo.kind() != kind()) + return BoolResult::err("Special functions can not be converted to function types."); + if (!equalExcludingStateMutability(convertTo)) return false; diff --git a/test/libsolidity/syntaxTests/abiEncoder/v2_call_to_v2_library_function_pointer_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v2_call_to_v2_library_function_pointer_accepting_struct.sol index 0a7919261..5682ede4d 100644 --- a/test/libsolidity/syntaxTests/abiEncoder/v2_call_to_v2_library_function_pointer_accepting_struct.sol +++ b/test/libsolidity/syntaxTests/abiEncoder/v2_call_to_v2_library_function_pointer_accepting_struct.sol @@ -22,4 +22,4 @@ contract Test { } } // ---- -// TypeError 9574: (B:269-313): Type function (struct L.Item memory) is not implicitly convertible to expected type function (struct L.Item memory) external. +// TypeError 9574: (B:269-313): Type function (struct L.Item memory) is not implicitly convertible to expected type function (struct L.Item memory) external. Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/events/event_library_function.sol b/test/libsolidity/syntaxTests/events/event_library_function.sol index 4eba5202f..382786faa 100644 --- a/test/libsolidity/syntaxTests/events/event_library_function.sol +++ b/test/libsolidity/syntaxTests/events/event_library_function.sol @@ -30,6 +30,6 @@ contract E { } } // ---- -// TypeError 9553: (140-143): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. -// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. -// TypeError 9553: (345-348): Invalid type for argument in function call. Invalid implicit conversion from function D.f() to function () external requested. +// TypeError 9553: (140-143): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. Special functions can not be converted to function types. +// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. Special functions can not be converted to function types. +// TypeError 9553: (345-348): Invalid type for argument in function call. Invalid implicit conversion from function D.f() to function () external requested. Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol b/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol index eac080e53..37322114d 100644 --- a/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol +++ b/test/libsolidity/syntaxTests/functionTypes/assign_bound.sol @@ -12,4 +12,4 @@ contract C { } } // ---- -// TypeError 9574: (209-280): Type function (uint256,uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). +// TypeError 9574: (209-280): Type function (uint256,uint256) pure returns (uint256) is not implicitly convertible to expected type function (uint256,uint256) pure returns (uint256). Bound functions can not be converted to non-bound functions. diff --git a/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol b/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol index 0fa43aa76..cb795fede 100644 --- a/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol +++ b/test/libsolidity/syntaxTests/functionTypes/assign_builtin.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError 9574: (42-103): Type function (uint256) view returns (bytes32) is not implicitly convertible to expected type function (uint256) view returns (bytes32). +// TypeError 9574: (42-103): Type function (uint256) view returns (bytes32) is not implicitly convertible to expected type function (uint256) view returns (bytes32). Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol index dbc873b39..0d7030606 100644 --- a/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol +++ b/test/libsolidity/syntaxTests/functionTypes/external_library_function_to_external_function_type.sol @@ -10,5 +10,5 @@ contract C { } } // ---- -// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) external returns (uint256) requested. -// TypeError 9574: (244-305): Type function (uint256) returns (uint256) is not implicitly convertible to expected type function (uint256) external returns (uint256). +// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) returns (uint256) to function (uint256) external returns (uint256) requested. Special functions can not be converted to function types. +// TypeError 9574: (244-305): Type function (uint256) returns (uint256) is not implicitly convertible to expected type function (uint256) external returns (uint256). Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol index cb2ee61c5..08b1b26e3 100644 --- a/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol @@ -3,4 +3,4 @@ contract test { function(bytes memory) external internal a = fa; } // ---- -// TypeError 7407: (106-108): Type function (bytes memory) is not implicitly convertible to expected type function (bytes memory) external. +// TypeError 7407: (106-108): Type function (bytes memory) is not implicitly convertible to expected type function (bytes memory) external. Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol index 699a0b551..2463bee5e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/262_bound_function_in_var.sol @@ -9,5 +9,5 @@ contract C { } } // ---- -// TypeError 9574: (218-271): Type function (struct D.s storage pointer,uint256) returns (uint256) is not implicitly convertible to expected type function (struct D.s storage pointer,uint256) returns (uint256). +// TypeError 9574: (218-271): Type function (struct D.s storage pointer,uint256) returns (uint256) is not implicitly convertible to expected type function (struct D.s storage pointer,uint256) returns (uint256). Bound functions can not be converted to non-bound functions. // TypeError 6160: (298-302): Wrong argument count for function call: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_base_name_to_var.sol b/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_base_name_to_var.sol index b3bff7849..9b988bb6e 100644 --- a/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_base_name_to_var.sol +++ b/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_base_name_to_var.sol @@ -10,5 +10,5 @@ contract B is A { } } // ---- -// TypeError 9574: (133-160): Type function A.f() is not implicitly convertible to expected type function () external. -// TypeError 9574: (170-202): Type function A.g() pure is not implicitly convertible to expected type function () pure external. +// TypeError 9574: (133-160): Type function A.f() is not implicitly convertible to expected type function () external. Special functions can not be converted to function types. +// TypeError 9574: (170-202): Type function A.g() pure is not implicitly convertible to expected type function () pure external. Special functions can not be converted to function types. diff --git a/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_contract_name_to_var.sol b/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_contract_name_to_var.sol index 655493d08..682a7a110 100644 --- a/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_contract_name_to_var.sol +++ b/test/libsolidity/syntaxTests/types/contractTypeType/members/assign_function_via_contract_name_to_var.sol @@ -10,5 +10,5 @@ contract B { } } // ---- -// TypeError 9574: (128-155): Type function A.f() is not implicitly convertible to expected type function () external. -// TypeError 9574: (165-197): Type function A.g() pure is not implicitly convertible to expected type function () pure external. +// TypeError 9574: (128-155): Type function A.f() is not implicitly convertible to expected type function () external. Special functions can not be converted to function types. +// TypeError 9574: (165-197): Type function A.g() pure is not implicitly convertible to expected type function () pure external. Special functions can not be converted to function types. From 03e805ab5a7ba6e7dd1a6cb320d916e3859448bf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 30 Nov 2020 14:38:21 +0000 Subject: [PATCH 12/29] Reformat FixedHash.h for readability --- libsolutil/FixedHash.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/libsolutil/FixedHash.h b/libsolutil/FixedHash.h index 84d6afba3..f2c2cbcc5 100644 --- a/libsolutil/FixedHash.h +++ b/libsolutil/FixedHash.h @@ -59,7 +59,13 @@ public: explicit FixedHash() { m_data.fill(0); } /// Construct from another hash, filling with zeroes or cropping as necessary. - template explicit FixedHash(FixedHash const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; } + template explicit FixedHash(FixedHash const& _h, ConstructFromHashType _t = AlignLeft) + { + m_data.fill(0); + unsigned c = std::min(M, N); + for (unsigned i = 0; i < c; ++i) + m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; + } /// Convert from the corresponding arithmetic type. FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } @@ -104,8 +110,10 @@ public: } } - /// Explicitly construct, copying from a string. - explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : solidity::util::asBytes(_s), _ht) {} + /// Explicitly construct, copying from a string. + explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): + FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : solidity::util::asBytes(_s), _ht) + {} /// Convert to arithmetic type. operator Arith() const { return fromBigEndian(m_data); } @@ -114,7 +122,16 @@ public: bool operator==(FixedHash const& _c) const { return m_data == _c.m_data; } bool operator!=(FixedHash const& _c) const { return m_data != _c.m_data; } /// Required to sort objects of this type or use them as map keys. - bool operator<(FixedHash const& _c) const { for (unsigned i = 0; i < N; ++i) if (m_data[i] < _c.m_data[i]) return true; else if (m_data[i] > _c.m_data[i]) return false; return false; } + bool operator<(FixedHash const& _c) const { + for (unsigned i = 0; i < N; ++i) + { + if (m_data[i] < _c.m_data[i]) + return true; + else if (m_data[i] > _c.m_data[i]) + return false; + } + return false; + } /// @returns a particular byte from the hash. uint8_t& operator[](unsigned _i) { return m_data[_i]; } From b40b82535cbff90d99690eff3dbf911f8da5a556 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 13 Dec 2019 02:59:45 +0000 Subject: [PATCH 13/29] Add comprehensive tests for FixedHash Also explicitly disallow FixedHash<0>, given most functions were not working with it, and it is not very useful. --- libsolutil/FixedHash.h | 1 + test/CMakeLists.txt | 1 + test/libsolutil/FixedHash.cpp | 272 ++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 test/libsolutil/FixedHash.cpp diff --git a/libsolutil/FixedHash.h b/libsolutil/FixedHash.h index f2c2cbcc5..dffeb7a17 100644 --- a/libsolutil/FixedHash.h +++ b/libsolutil/FixedHash.h @@ -48,6 +48,7 @@ public: /// The size of the container. enum { size = N }; + static_assert(N != 0); /// Method to convert from a string. enum ConstructFromStringType { FromHex, FromBinary }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index caa587415..f7adf16a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -29,6 +29,7 @@ detect_stray_source_files("${contracts_sources}" "contracts/") set(libsolutil_sources libsolutil/Checksum.cpp libsolutil/CommonData.cpp + libsolutil/FixedHash.cpp libsolutil/IndentedWriter.cpp libsolutil/IpfsHash.cpp libsolutil/IterateReplacing.cpp diff --git a/test/libsolutil/FixedHash.cpp b/test/libsolutil/FixedHash.cpp new file mode 100644 index 000000000..4efe0a9e1 --- /dev/null +++ b/test/libsolutil/FixedHash.cpp @@ -0,0 +1,272 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * Unit tests for FixedHash. + */ + +#include + +#include + +#include +#include + +using namespace std; + +namespace solidity::util::test +{ + +static_assert(std::is_same>()); +static_assert(std::is_same>()); + +BOOST_AUTO_TEST_SUITE(FixedHashTest) + +BOOST_AUTO_TEST_CASE(default_constructor) +{ + BOOST_CHECK_EQUAL( + FixedHash<1>{}.hex(), + "00" + ); + BOOST_CHECK_EQUAL( + FixedHash<1>{}.size, + 1 + ); + BOOST_CHECK_EQUAL( + FixedHash<8>{}.hex(), + "0000000000000000" + ); + BOOST_CHECK_EQUAL( + FixedHash<8>{}.size, + 8 + ); + BOOST_CHECK_EQUAL( + FixedHash<20>{}.hex(), + "0000000000000000000000000000000000000000" + ); + BOOST_CHECK_EQUAL( + FixedHash<20>{}.size, + 20 + ); + BOOST_CHECK_EQUAL( + FixedHash<32>{}.hex(), + "0000000000000000000000000000000000000000000000000000000000000000" + ); + BOOST_CHECK_EQUAL( + FixedHash<32>{}.size, + 32 + ); +} + +BOOST_AUTO_TEST_CASE(bytes_constructor) +{ + FixedHash<8> a(bytes{}); + BOOST_CHECK_EQUAL(a.size, 8); + BOOST_CHECK_EQUAL(a.hex(), "0000000000000000"); + + FixedHash<8> b(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}); + BOOST_CHECK_EQUAL(b.size, 8); + BOOST_CHECK_EQUAL(b.hex(), "1122334455667788"); + + // TODO: short input, this should fail + FixedHash<8> c(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}); + BOOST_CHECK_EQUAL(c.size, 8); + BOOST_CHECK_EQUAL(c.hex(), "0000000000000000"); + + // TODO: oversized input, this should fail + FixedHash<8> d(bytes{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}); + BOOST_CHECK_EQUAL(d.size, 8); + BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); +} + +// TODO: add FixedHash(bytesConstRef) constructor + +BOOST_AUTO_TEST_CASE(string_constructor_fromhex) +{ + // TODO: this tests the default settings ConstructFromStringType::fromHex, ConstructFromHashType::FailIfDifferent + // should test other options too + + FixedHash<8> a(""); + BOOST_CHECK_EQUAL(a.size, 8); + BOOST_CHECK_EQUAL(a.hex(), "0000000000000000"); + + FixedHash<8> b("1122334455667788"); + BOOST_CHECK_EQUAL(b.size, 8); + BOOST_CHECK_EQUAL(b.hex(), "1122334455667788"); + + FixedHash<8> c("0x1122334455667788"); + BOOST_CHECK_EQUAL(c.size, 8); + BOOST_CHECK_EQUAL(c.hex(), "1122334455667788"); + + // TODO: short input, this should fail + FixedHash<8> d("112233445566"); + BOOST_CHECK_EQUAL(d.size, 8); + BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); + + // TODO: oversized input, this should fail + FixedHash<8> e("112233445566778899"); + BOOST_CHECK_EQUAL(e.size, 8); + BOOST_CHECK_EQUAL(e.hex(), "0000000000000000"); +} + +BOOST_AUTO_TEST_CASE(string_constructor_frombytes) +{ + + FixedHash<8> b("", FixedHash<8>::FromBinary); + BOOST_CHECK_EQUAL(b.size, 8); + BOOST_CHECK_EQUAL(b.hex(), "0000000000000000"); + + FixedHash<8> c("abcdefgh", FixedHash<8>::FromBinary); + BOOST_CHECK_EQUAL(c.size, 8); + BOOST_CHECK_EQUAL(c.hex(), "6162636465666768"); + + // TODO: short input, this should fail + FixedHash<8> d("abcdefg", FixedHash<8>::FromBinary); + BOOST_CHECK_EQUAL(d.size, 8); + BOOST_CHECK_EQUAL(d.hex(), "0000000000000000"); + + // TODO: oversized input, this should fail + FixedHash<8> e("abcdefghi", FixedHash<8>::FromBinary); + BOOST_CHECK_EQUAL(e.size, 8); + BOOST_CHECK_EQUAL(e.hex(), "0000000000000000"); +} + +BOOST_AUTO_TEST_CASE(converting_constructor) +{ + // Truncation + FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122")); + BOOST_CHECK_EQUAL(a.size, 8); + BOOST_CHECK_EQUAL(a.hex(), "1122334455667788"); + + // Left-aligned extension + FixedHash<12> b = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); + BOOST_CHECK_EQUAL(b.size, 12); + BOOST_CHECK_EQUAL(b.hex(), "112233445566778800000000"); + + // Right-aligned extension + FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); + BOOST_CHECK_EQUAL(c.size, 12); + BOOST_CHECK_EQUAL(c.hex(), "000000001122334455667788"); + + // Default setting + FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788")); + BOOST_CHECK_EQUAL(d, b); + + // FailIfDifferent setting + // TODO: Shouldn't this throw? + FixedHash<12> e = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::FailIfDifferent); + BOOST_CHECK_EQUAL(e, b); +} + +BOOST_AUTO_TEST_CASE(arith_constructor) +{ + FixedHash<20> a(u160(0x1234)); + BOOST_CHECK_EQUAL( + a.hex(), + "0000000000000000000000000000000000001234" + ); + + FixedHash<32> b(u256(0x12340000)); + BOOST_CHECK_EQUAL( + b.hex(), + "0000000000000000000000000000000000000000000000000000000012340000" + ); + + // NOTE: size-mismatched constructor is not available +} + +BOOST_AUTO_TEST_CASE(to_arith) +{ + FixedHash<20> a{}; + BOOST_CHECK_EQUAL(u160(a), 0); + + FixedHash<32> b("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + BOOST_CHECK_EQUAL(u256(b), u256("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); +} + +BOOST_AUTO_TEST_CASE(comparison) +{ + FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + FixedHash<32> b("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + FixedHash<32> c("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a471"); + FixedHash<32> d("233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470c5d2460186f7"); + + BOOST_CHECK(a == a); + BOOST_CHECK(b == b); + BOOST_CHECK(a == b); + BOOST_CHECK(b == a); + BOOST_CHECK(a != c); + BOOST_CHECK(c != a); + BOOST_CHECK(a != d); + BOOST_CHECK(d != a); + + // Only equal size comparison is supported. + BOOST_CHECK(FixedHash<8>{} == FixedHash<8>{}); + BOOST_CHECK(FixedHash<32>{} != b); + + // Only equal size less than comparison is supported. + BOOST_CHECK(!(a < b)); + BOOST_CHECK(d < c); + BOOST_CHECK(FixedHash<32>{} < a); +} + +BOOST_AUTO_TEST_CASE(indexing) +{ + // NOTE: uses std::array, so "Accessing a nonexistent element through this operator is undefined behavior." + + FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + BOOST_CHECK_EQUAL(a[0], 0xc5); + BOOST_CHECK_EQUAL(a[1], 0xd2); + BOOST_CHECK_EQUAL(a[31], 0x70); + a[0] = 0xff; + a[31] = 0x54; + BOOST_CHECK_EQUAL(a[0], 0xff); + BOOST_CHECK_EQUAL(a[1], 0xd2); + BOOST_CHECK_EQUAL(a[31], 0x54); +} + +BOOST_AUTO_TEST_CASE(misc) +{ + FixedHash<32> a("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + + uint8_t* mut_a = a.data(); + uint8_t const* const_a = a.data(); + BOOST_CHECK_EQUAL(mut_a, const_a); + BOOST_CHECK_EQUAL(memcmp(mut_a, const_a, a.size), 0); + + bytes bytes_a = a.asBytes(); + bytesRef bytesref_a = a.ref(); + bytesConstRef bytesconstref_a = a.ref(); + + // There's no printing for bytesRef/bytesConstRef + BOOST_CHECK(bytes(a.data(), a.data() + a.size) == bytes_a); + BOOST_CHECK(bytesRef(a.data(), a.size) == bytesref_a); + BOOST_CHECK(bytesConstRef(a.data(), a.size) == bytesconstref_a); +} + +BOOST_AUTO_TEST_CASE(tostream) +{ + std::ostringstream out; + out << FixedHash<4>("44114411"); + out << FixedHash<32>{}; + out << FixedHash<2>("f77f"); + out << FixedHash<1>("1"); + BOOST_CHECK_EQUAL(out.str(), "441144110000000000000000000000000000000000000000000000000000000000000000f77f01"); +} + +BOOST_AUTO_TEST_SUITE_END() + +} From 98d8174d31f70c425c3c9f5ced3dac0edad703b4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 17 Nov 2020 16:50:42 +0000 Subject: [PATCH 14/29] Simplify Compiler/CompilerContext by removing extra layers of indirection --- libsolidity/codegen/Compiler.h | 22 +++---------------- libsolidity/codegen/CompilerContext.cpp | 7 ------ libsolidity/codegen/CompilerContext.h | 15 ------------- libsolidity/interface/CompilerStack.cpp | 15 +++++++------ test/libsolidity/Assembly.cpp | 2 +- .../SolidityExpressionCompiler.cpp | 6 ++++- 6 files changed, 17 insertions(+), 50 deletions(-) diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 4dbbeb099..6e6fd968e 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -51,28 +51,12 @@ public: ); /// @returns Entire assembly. evmasm::Assembly const& assembly() const { return m_context.assembly(); } + /// @returns Runtime assembly. + evmasm::Assembly const& runtimeAssembly() const { return m_context.assembly().sub(m_runtimeSub); } /// @returns Entire assembly as a shared pointer to non-const. std::shared_ptr assemblyPtr() const { return m_context.assemblyPtr(); } - /// @returns Runtime assembly. + /// @returns Runtime assembly as a shared pointer. std::shared_ptr runtimeAssemblyPtr() const; - /// @returns The entire assembled object (with constructor). - evmasm::LinkerObject assembledObject() const { return m_context.assembledObject(); } - /// @returns Only the runtime object (without constructor). - evmasm::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); } - /// @arg _sourceCodes is the map of input files to source code strings - std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const - { - return m_context.assemblyString(_sourceCodes); - } - /// @arg _sourceCodes is the map of input files to source code strings - Json::Value assemblyJSON(std::map const& _indices = std::map()) const - { - return m_context.assemblyJSON(_indices); - } - /// @returns Assembly items of the normal compiler context - evmasm::AssemblyItems const& assemblyItems() const { return m_context.assembly().items(); } - /// @returns Assembly items of the runtime compiler context - evmasm::AssemblyItems const& runtimeAssemblyItems() const { return m_context.assembly().sub(m_runtimeSub).items(); } std::string generatedYulUtilityCode() const { return m_context.generatedYulUtilityCode(); } std::string runtimeGeneratedYulUtilityCode() const { return m_runtimeContext.generatedYulUtilityCode(); } diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index dcee585be..0600dfb3a 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -548,13 +548,6 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ #endif } -LinkerObject const& CompilerContext::assembledObject() const -{ - LinkerObject const& object = m_asm->assemble(); - solAssert(object.immutableReferences.empty(), "Leftover immutables."); - return object; -} - string CompilerContext::revertReasonIfDebug(string const& _message) { return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index d32349e89..ddb68c912 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -287,21 +287,6 @@ public: /// Should be avoided except when adding sub-assemblies. std::shared_ptr assemblyPtr() const { return m_asm; } - /// @arg _sourceCodes is the map of input files to source code strings - std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const - { - return m_asm->assemblyString(_sourceCodes); - } - - /// @arg _sourceCodes is the map of input files to source code strings - Json::Value assemblyJSON(std::map const& _indicies = std::map()) const - { - return m_asm->assemblyJSON(_indicies); - } - - evmasm::LinkerObject const& assembledObject() const; - evmasm::LinkerObject const& assembledRuntimeObject(size_t _subIndex) const { return m_asm->sub(_subIndex).assemble(); } - /** * Helper class to pop the visited nodes stack when a scope closes */ diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 90c809e13..bab844751 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -627,7 +627,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contrac BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - return currentContract.compiler ? &contract(_contractName).compiler->assemblyItems() : nullptr; + return currentContract.compiler ? &contract(_contractName).compiler->assembly()->items() : nullptr; } evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const @@ -636,7 +636,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssemblyItems() : nullptr; + return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssembly()->items() : nullptr; } Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const @@ -791,7 +791,7 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap _sou Contract const& currentContract = contract(_contractName); if (currentContract.compiler) - return currentContract.compiler->assemblyString(_sourceCodes); + return currentContract.compiler->assembly().assemblyString(_sourceCodes); else return string(); } @@ -804,7 +804,7 @@ Json::Value CompilerStack::assemblyJSON(string const& _contractName) const Contract const& currentContract = contract(_contractName); if (currentContract.compiler) - return currentContract.compiler->assemblyJSON(sourceIndices()); + return currentContract.compiler->assembly().assemblyJSON(sourceIndices()); else return Json::Value(); } @@ -977,7 +977,7 @@ size_t CompilerStack::functionEntryPoint( evmasm::AssemblyItem tag = compiler->functionEntryLabel(_function); if (tag.type() == evmasm::UndefinedItem) return 0; - evmasm::AssemblyItems const& items = compiler->runtimeAssemblyItems(); + evmasm::AssemblyItems const& items = compiler->runtimeAssembly().items(); for (size_t i = 0; i < items.size(); ++i) if (items.at(i).type() == evmasm::Tag && items.at(i).data() == tag.data()) return i; @@ -1203,17 +1203,18 @@ void CompilerStack::compileContract( try { // Assemble deployment (incl. runtime) object. - compiledContract.object = compiler->assembledObject(); + compiledContract.object = compiler->assembly().assemble(); } catch(evmasm::AssemblyException const&) { solAssert(false, "Assembly exception for bytecode"); } + solAssert(compiledContract.object.immutableReferences.empty(), "Leftover immutables."); try { // Assemble runtime object. - compiledContract.runtimeObject = compiler->runtimeObject(); + compiledContract.runtimeObject = compiler->runtimeAssembly().assemble(); } catch(evmasm::AssemblyException const&) { diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 4b599da68..676f63313 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -91,7 +91,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) ); compiler.compileContract(*contract, map>{}, bytes()); - return compiler.runtimeAssemblyItems(); + return compiler.runtimeAssembly().items(); } BOOST_FAIL("No contract found in source."); return AssemblyItems(); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index d5644a38d..15a67e6fe 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -160,7 +161,10 @@ bytes compileFirstExpression( context << context.functionEntryLabel(dynamic_cast( resolveDeclaration(*sourceUnit, function, resolver) )); - bytes instructions = context.assembledObject().bytecode; + BOOST_REQUIRE(context.assemblyPtr()); + LinkerObject const& object = context.assemblyPtr()->assemble(); + BOOST_REQUIRE(object.immutableReferences.empty()); + bytes instructions = object.bytecode; // debug // cout << evmasm::disassemble(instructions) << endl; return instructions; From bcaefb57b8482b26b6c71b51995d7748761edb09 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 17 Nov 2020 23:05:18 +0000 Subject: [PATCH 15/29] Add evmAssembly and evmRuntimeAssembly pointer in CompilerStack This is a preparation for allowing those outputs to be served from the IR too --- libsolidity/interface/CompilerStack.cpp | 20 ++++++++++++-------- libsolidity/interface/CompilerStack.h | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index bab844751..245579a0a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -627,7 +627,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contrac BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - return currentContract.compiler ? &contract(_contractName).compiler->assembly()->items() : nullptr; + return currentContract.evmAssembly ? ¤tContract.evmAssembly->items() : nullptr; } evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const @@ -636,7 +636,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssembly()->items() : nullptr; + return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr; } Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const @@ -790,8 +790,8 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap _sou BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - if (currentContract.compiler) - return currentContract.compiler->assembly().assemblyString(_sourceCodes); + if (currentContract.evmAssembly) + return currentContract.evmAssembly->assemblyString(_sourceCodes); else return string(); } @@ -803,8 +803,8 @@ Json::Value CompilerStack::assemblyJSON(string const& _contractName) const BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); Contract const& currentContract = contract(_contractName); - if (currentContract.compiler) - return currentContract.compiler->assembly().assemblyJSON(sourceIndices()); + if (currentContract.evmAssembly) + return currentContract.evmAssembly->assemblyJSON(sourceIndices()); else return Json::Value(); } @@ -1200,10 +1200,12 @@ void CompilerStack::compileContract( solAssert(false, "Optimizer exception during compilation"); } + compiledContract.evmAssembly = compiler->assemblyPtr(); + solAssert(compiledContract.evmAssembly, ""); try { // Assemble deployment (incl. runtime) object. - compiledContract.object = compiler->assembly().assemble(); + compiledContract.object = compiledContract.evmAssembly->assemble(); } catch(evmasm::AssemblyException const&) { @@ -1211,10 +1213,12 @@ void CompilerStack::compileContract( } solAssert(compiledContract.object.immutableReferences.empty(), "Leftover immutables."); + compiledContract.evmRuntimeAssembly = compiler->runtimeAssemblyPtr(); + solAssert(compiledContract.evmRuntimeAssembly, ""); try { // Assemble runtime object. - compiledContract.runtimeObject = compiler->runtimeAssembly().assemble(); + compiledContract.runtimeObject = compiledContract.evmRuntimeAssembly->assemble(); } catch(evmasm::AssemblyException const&) { diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index eb4e7d8a7..631f574cd 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -358,6 +358,8 @@ private: { ContractDefinition const* contract = nullptr; std::shared_ptr compiler; + std::shared_ptr evmAssembly; + std::shared_ptr evmRuntimeAssembly; evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject runtimeObject; ///< Runtime object. std::string yulIR; ///< Experimental Yul IR code. From 4a7f2ddc6decb8f53a9a548977f56c88661e7a8d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 25 Nov 2020 00:41:26 +0000 Subject: [PATCH 16/29] Properly print sources in ASTJSONTest --- test/libsolidity/ASTJSONTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp index 6258c9e59..8e93fe9f2 100644 --- a/test/libsolidity/ASTJSONTest.cpp +++ b/test/libsolidity/ASTJSONTest.cpp @@ -281,7 +281,7 @@ void ASTJSONTest::printSource(ostream& _stream, string const& _linePrefix, bool for (auto const& source: m_sources) { if (m_sources.size() > 1 || source.first != "a") - _stream << _linePrefix << sourceDelimiter << source.first << endl << endl; + _stream << _linePrefix << sourceDelimiter << source.first << " ====" << endl << endl; stringstream stream(source.second); string line; while (getline(stream, line)) From 8927015e5a06d273b4ba82c69fa553959e8bb5db Mon Sep 17 00:00:00 2001 From: Martin Blicha Date: Thu, 10 Dec 2020 16:51:10 +0100 Subject: [PATCH 17/29] [SMTChecker] Adding unary increment and decrement as under/overflow verification targets for the CHC engine --- Changelog.md | 1 + libsolidity/formal/BMC.cpp | 17 +---------- libsolidity/formal/SMTEncoder.cpp | 16 +++++++++-- .../array_members/pop_loop_safe.sol | 2 ++ .../array_members/pop_loop_unsafe.sol | 1 + ...overflow_2_safe_no_overflow_assumption.sol | 2 ++ .../unary_add_minus_overflow_detected.sol | 28 +++++++++++++++++++ .../smtCheckerTests/control_flow/return_1.sol | 1 - .../control_flow/return_1_fail.sol | 1 - .../smtCheckerTests/control_flow/return_2.sol | 1 - .../control_flow/return_2_fail.sol | 1 - .../external_calls/external_inc.sol | 1 + .../external_calls/external_safe.sol | 3 ++ .../internal_call_with_assertion_1.sol | 2 -- .../internal_call_with_assertion_1_fail.sol | 2 -- ...rnal_call_with_assertion_inheritance_1.sol | 2 -- ...call_with_assertion_inheritance_1_fail.sol | 2 -- ...ternal_multiple_calls_with_assertion_1.sol | 4 --- ...l_multiple_calls_with_assertion_1_fail.sol | 4 --- .../smtCheckerTests/imports/import_base.sol | 1 + .../smtCheckerTests/invariants/loop_basic.sol | 2 ++ .../invariants/loop_basic_for.sol | 2 ++ .../loops/while_2_break_fail.sol | 2 +- ...le_loop_array_assignment_memory_memory.sol | 3 +- ...e_loop_array_assignment_memory_storage.sol | 1 + ..._loop_array_assignment_storage_storage.sol | 1 + .../assignment_contract_member_variable.sol | 7 +++-- .../operators/conditional_assignment_3.sol | 2 +- .../conditional_assignment_statevar_1.sol | 3 ++ .../operators/unary_add_array.sol | 2 +- .../operators/unary_add_mapping.sol | 4 ++- .../unary_add_minus_overflow_detected.sol | 25 +++++++++++++++++ .../unary_add_overflows_correctly.sol | 16 +++++++++++ .../unary_add_overflows_correctly_struct.sol | 24 ++++++++++++++++ .../operators/unary_sub_array.sol | 2 +- .../operators/unary_sub_mapping.sol | 2 +- .../types/struct/struct_recursive_6.sol | 12 +++----- .../types/struct/struct_unary_add.sol | 2 +- .../types/struct/struct_unary_sub.sol | 2 +- .../smtCheckerTests/types/unused_mapping.sol | 3 +- 40 files changed, 150 insertions(+), 59 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/bmc_coverage/unary_add_minus_overflow_detected.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/unary_add_minus_overflow_detected.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly.sol create mode 100644 test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly_struct.sol diff --git a/Changelog.md b/Changelog.md index 10944f1be..fa01287e4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Compiler Features: * SMTChecker: Support getters. * SMTChecker: Support named arguments in function calls. * SMTChecker: Support struct constructor. + * SMTChecker: Create underflow and overflow verification targets for increment/decrement in the CHC engine. * Standard-Json: Move the recently introduced ``modelCheckerSettings`` key to ``settings.modelChecker``. * Standard-Json: Properly filter the requested output artifacts. diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 1b47a24f5..393aa1022 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -356,27 +356,12 @@ void BMC::endVisit(UnaryOperation const& _op) ) return; - switch (_op.getOperator()) - { - case Token::Inc: // ++ (pre- or postfix) - case Token::Dec: // -- (pre- or postfix) + if (_op.getOperator() == Token::Sub && smt::isInteger(*_op.annotation().type)) addVerificationTarget( VerificationTarget::Type::UnderOverflow, expr(_op), &_op ); - break; - case Token::Sub: // - - if (_op.annotation().type->category() == Type::Category::Integer) - addVerificationTarget( - VerificationTarget::Type::UnderOverflow, - expr(_op), - &_op - ); - break; - default: - break; - } } void BMC::endVisit(FunctionCall const& _funCall) diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index c704e5ab1..be67326c3 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -512,7 +512,13 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) auto decl = identifierToVariable(*identifier); solAssert(decl, ""); auto innerValue = currentValue(*decl); - auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1; + auto newValue = arithmeticOperation( + _op.getOperator() == Token::Inc ? Token::Add : Token::Sub, + innerValue, + smtutil::Expression(size_t(1)), + _op.annotation().type, + _op + ).first; defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); assignment(*decl, newValue); } @@ -522,7 +528,13 @@ void SMTEncoder::endVisit(UnaryOperation const& _op) ) { auto innerValue = expr(*subExpr); - auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1; + auto newValue = arithmeticOperation( + _op.getOperator() == Token::Inc ? Token::Add : Token::Sub, + innerValue, + smtutil::Expression(size_t(1)), + _op.annotation().type, + _op + ).first; defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue); indexOrMemberAssignment(*subExpr, newValue); } diff --git a/test/libsolidity/smtCheckerTests/array_members/pop_loop_safe.sol b/test/libsolidity/smtCheckerTests/array_members/pop_loop_safe.sol index 25986da7b..4626a7d08 100644 --- a/test/libsolidity/smtCheckerTests/array_members/pop_loop_safe.sol +++ b/test/libsolidity/smtCheckerTests/array_members/pop_loop_safe.sol @@ -9,3 +9,5 @@ contract C { } } } +// ---- +// Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/array_members/pop_loop_unsafe.sol b/test/libsolidity/smtCheckerTests/array_members/pop_loop_unsafe.sol index 3151df0dc..deac0b2c9 100644 --- a/test/libsolidity/smtCheckerTests/array_members/pop_loop_unsafe.sol +++ b/test/libsolidity/smtCheckerTests/array_members/pop_loop_unsafe.sol @@ -11,4 +11,5 @@ contract C { } } // ---- +// Warning 4984: (112-115): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 2529: (150-157): CHC: Empty array "pop" happens here.\nCounterexample:\na = []\nl = 0\n\n\nTransaction trace:\nconstructor()\nState: a = []\nf(0) diff --git a/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol b/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol index 1f468f592..21c96a7bd 100644 --- a/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol +++ b/test/libsolidity/smtCheckerTests/array_members/push_overflow_2_safe_no_overflow_assumption.sol @@ -11,3 +11,5 @@ contract C { assert(x[0] == 42); } } +// ---- +// Warning 4984: (174-177): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/bmc_coverage/unary_add_minus_overflow_detected.sol b/test/libsolidity/smtCheckerTests/bmc_coverage/unary_add_minus_overflow_detected.sol new file mode 100644 index 000000000..9d375fd58 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/bmc_coverage/unary_add_minus_overflow_detected.sol @@ -0,0 +1,28 @@ +pragma experimental SMTChecker; +contract C { + uint8 x; + + function inc_pre() public { + ++x; + } + + function dec_pre() public { + --x; + } + + /* Commented out because Spacer segfaults in Z3 4.8.9 + function inc_post() public { + x++; + } + + function dec_post() public { + x--; + } + */ + +} +// ==== +// SMTEngine: bmc +// ---- +// Warning 2661: (87-90): BMC: Overflow (resulting value larger than 255) happens here. +// Warning 4144: (127-130): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/control_flow/return_1.sol b/test/libsolidity/smtCheckerTests/control_flow/return_1.sol index 881ec7cc0..3dabd2fef 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/return_1.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/return_1.sol @@ -19,4 +19,3 @@ contract C { } } // ---- -// Warning 2661: (158-161): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/control_flow/return_1_fail.sol b/test/libsolidity/smtCheckerTests/control_flow/return_1_fail.sol index 21c655980..02b88c981 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/return_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/return_1_fail.sol @@ -23,4 +23,3 @@ contract C { // Warning 6328: (274-300): CHC: Assertion violation happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() // Warning 6328: (304-330): CHC: Assertion violation happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() // Warning 6328: (334-362): CHC: Assertion violation happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() -// Warning 2661: (158-161): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/control_flow/return_2.sol b/test/libsolidity/smtCheckerTests/control_flow/return_2.sol index ec3546e4f..c6005bb08 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/return_2.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/return_2.sol @@ -28,4 +28,3 @@ contract C { } } // ---- -// Warning 2661: (188-191): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/control_flow/return_2_fail.sol b/test/libsolidity/smtCheckerTests/control_flow/return_2_fail.sol index 8ec948345..34c798a2a 100644 --- a/test/libsolidity/smtCheckerTests/control_flow/return_2_fail.sol +++ b/test/libsolidity/smtCheckerTests/control_flow/return_2_fail.sol @@ -38,4 +38,3 @@ contract C { // Warning 6328: (437-458): CHC: Assertion violation happens here. // Warning 6328: (462-490): CHC: Assertion violation happens here. // Warning 6328: (494-517): CHC: Assertion violation happens here. -// Warning 2661: (188-191): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol b/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol index 9f6ce11a8..412456cd4 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_inc.sol @@ -18,5 +18,6 @@ contract C { } } // ---- +// Warning 4984: (146-149): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 6328: (189-203): CHC: Assertion violation happens here.\nCounterexample:\nx = 10, d = 0\n\n\n\nTransaction trace:\nconstructor()\nState: x = 0, d = 0\ninc()\nState: x = 1, d = 0\nf() // Warning 2661: (146-149): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol index 6a2b66491..aa4a8a6c1 100644 --- a/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol +++ b/test/libsolidity/smtCheckerTests/external_calls/external_safe.sol @@ -16,3 +16,6 @@ contract C { assert(x < 11); } } +// ---- +// Warning 6328: (200-214): CHC: Assertion violation might happen here. +// Warning 4661: (200-214): BMC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1.sol index dba4f11ee..52dcfb1ff 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1.sol @@ -21,5 +21,3 @@ contract C{ } // ---- // Warning 5667: (70-76): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning 2661: (156-159): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (238-241): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1_fail.sol index dae611717..a1e245fd9 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_1_fail.sol @@ -26,5 +26,3 @@ contract C{ // Warning 6328: (220-234): CHC: Assertion violation happens here.\nCounterexample:\nx = 2\n\n\n\nTransaction trace:\nconstructor(0)\nState: x = 1\nf() // Warning 6328: (245-259): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\n\n\nTransaction trace:\nconstructor(0)\nState: x = 1\nf() // Warning 6328: (82-96): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\ny = 0\n\n\nTransaction trace:\nconstructor(0) -// Warning 2661: (156-159): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (238-241): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1.sol index 19a1ceb2f..80f6d6304 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1.sol @@ -17,5 +17,3 @@ contract C is A { } } // ---- -// Warning 4144: (100-103): BMC: Underflow (resulting value less than 0) happens here. -// Warning 4144: (100-103): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol index 303f72504..3052258fc 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_call_with_assertion_inheritance_1_fail.sol @@ -20,5 +20,3 @@ contract C is A { // Warning 6328: (82-96): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\n\n\nTransaction trace:\nconstructor() // Warning 6328: (148-162): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\n\n\nTransaction trace:\nconstructor() // Warning 6328: (180-194): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\n\n\n\nTransaction trace:\nconstructor() -// Warning 4144: (100-103): BMC: Underflow (resulting value less than 0) happens here. -// Warning 4144: (100-103): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1.sol b/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1.sol index ffb9d48cd..f23217cde 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1.sol @@ -21,7 +21,3 @@ contract C{ } // ---- // Warning 5667: (70-76): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning 2661: (156-159): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 2661: (163-166): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 2661: (234-237): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (234-237): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1_fail.sol index c606dd1cc..81ba33295 100644 --- a/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/internal_multiple_calls_with_assertion_1_fail.sol @@ -24,7 +24,3 @@ contract C{ // Warning 6328: (138-152): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\n\n\nTransaction trace:\nconstructor(0)\nState: x = 1\nf() // Warning 6328: (184-198): CHC: Assertion violation happens here.\nCounterexample:\nx = 1\n\n\n\nTransaction trace:\nconstructor(0)\nState: x = 1\nf() // Warning 6328: (82-96): CHC: Assertion violation happens here.\nCounterexample:\nx = 0\ny = 0\n\n\nTransaction trace:\nconstructor(0) -// Warning 2661: (156-159): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 2661: (163-166): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 2661: (234-237): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (234-237): BMC: Underflow (resulting value less than 0) happens here. diff --git a/test/libsolidity/smtCheckerTests/imports/import_base.sol b/test/libsolidity/smtCheckerTests/imports/import_base.sol index f02265c75..223365c5a 100644 --- a/test/libsolidity/smtCheckerTests/imports/import_base.sol +++ b/test/libsolidity/smtCheckerTests/imports/import_base.sol @@ -20,6 +20,7 @@ contract Der is Base { // ---- // Warning 4984: (der:101-109): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 6328: (der:113-126): CHC: Assertion violation happens here.\nCounterexample:\nx = 3, a = 0\ny = 0\n\n\nTransaction trace:\nconstructor()\nState: x = 0, a = 0\ng(0) +// Warning 4984: (base:100-103): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 2661: (base:100-103): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 2661: (der:101-109): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. // Warning 2661: (base:100-103): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/invariants/loop_basic.sol b/test/libsolidity/smtCheckerTests/invariants/loop_basic.sol index d24b19e1e..98d1ea384 100644 --- a/test/libsolidity/smtCheckerTests/invariants/loop_basic.sol +++ b/test/libsolidity/smtCheckerTests/invariants/loop_basic.sol @@ -11,3 +11,5 @@ contract Simple { } // ==== // SMTSolvers: z3 +// ---- +// Warning 4984: (132-135): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/invariants/loop_basic_for.sol b/test/libsolidity/smtCheckerTests/invariants/loop_basic_for.sol index 3e059b516..bc3814ccc 100644 --- a/test/libsolidity/smtCheckerTests/invariants/loop_basic_for.sol +++ b/test/libsolidity/smtCheckerTests/invariants/loop_basic_for.sol @@ -9,3 +9,5 @@ contract Simple { } // ==== // SMTSolvers: z3 +// ---- +// Warning 4984: (116-119): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/loops/while_2_break_fail.sol b/test/libsolidity/smtCheckerTests/loops/while_2_break_fail.sol index 0012c9c7b..88ade1cd4 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_2_break_fail.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_2_break_fail.sol @@ -15,4 +15,4 @@ contract C // SMTSolvers: z3 // ---- // Warning 5740: (120-123): Unreachable code. -// Warning 6328: (131-145): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 1\n\n\nTransaction trace:\nconstructor()\nf(1) +// Warning 6328: (131-145): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 3\n\n\nTransaction trace:\nconstructor()\nf(3) diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_memory.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_memory.sol index aeba1381b..3ea615a2a 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_memory.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_memory.sol @@ -18,9 +18,10 @@ contract LoopFor2 { } } // ==== -// SMTSolvers: z3 // SMTIgnoreCex: yes +// SMTSolvers: z3 // ---- // Warning 4984: (244-249): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. +// Warning 4984: (270-273): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 6328: (373-392): CHC: Assertion violation happens here. // Warning 6328: (396-415): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_storage.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_storage.sol index 29509fc5c..e37bf2dbf 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_storage.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_memory_storage.sol @@ -26,3 +26,4 @@ contract LoopFor2 { // SMTSolvers: z3 // ---- // Warning 4984: (237-242): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. +// Warning 4984: (263-266): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol index 47137aec5..2aae73453 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_array_assignment_storage_storage.sol @@ -21,5 +21,6 @@ contract LoopFor2 { } // ---- // Warning 4984: (229-234): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. +// Warning 4984: (255-258): CHC: Overflow (resulting value larger than 2**256 - 1) might happen here. // Warning 6328: (338-357): CHC: Assertion violation happens here.\nCounterexample:\nb = [], c = []\nn = 1\n\n\nTransaction trace:\nconstructor()\nState: b = [], c = []\ntestUnboundedForLoop(1) // Warning 6328: (361-380): CHC: Assertion violation happens here.\nCounterexample:\nb = [], c = []\nn = 1\n\n\nTransaction trace:\nconstructor()\nState: b = [], c = []\ntestUnboundedForLoop(1) diff --git a/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol b/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol index ae8725b54..b0b16783b 100644 --- a/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol +++ b/test/libsolidity/smtCheckerTests/operators/assignment_contract_member_variable.sol @@ -7,7 +7,7 @@ contract A { A.y = A.x++; assert(A.y == A.x - 1); // Fails - assert(A.y == 0); + // assert(A.y == 0); // Disabled because of nondeterminism in Spacer A.y = ++A.x; assert(A.y == A.x); delete A.x; @@ -25,6 +25,7 @@ contract A { assert(A.y == A.x); } } +// ==== +// SMTIgnoreCex: yes // ---- -// Warning 6328: (160-176): CHC: Assertion violation happens here.\nCounterexample:\nx = (- 1), y = (- 2)\n\n\n\nTransaction trace:\nconstructor()\nState: x = 0, y = 0\na()\nState: x = (- 2), y = (- 2)\na() -// Warning 6328: (373-389): CHC: Assertion violation happens here.\nCounterexample:\nx = 8, y = (- 2)\n\n\n\nTransaction trace:\nconstructor()\nState: x = 0, y = 0\na() +// Warning 6328: (424-440): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_3.sol b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_3.sol index 88da0e05a..e8a400493 100644 --- a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_3.sol +++ b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_3.sol @@ -10,4 +10,4 @@ contract C { } } // ---- -// Warning 6328: (161-174): CHC: Assertion violation happens here.\nCounterexample:\n\na = 6\nb = 5\n\n\nTransaction trace:\nconstructor()\nf(5, 5) +// Warning 6328: (161-174): CHC: Assertion violation happens here.\nCounterexample:\n\na = 0\nb = 1\n\n\nTransaction trace:\nconstructor()\nf(0, 0) diff --git a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_statevar_1.sol b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_statevar_1.sol index 3c402fceb..3df380fef 100644 --- a/test/libsolidity/smtCheckerTests/operators/conditional_assignment_statevar_1.sol +++ b/test/libsolidity/smtCheckerTests/operators/conditional_assignment_statevar_1.sol @@ -10,3 +10,6 @@ contract C { } } // ---- +// Warning 4984: (129-134): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\na = 115792089237316195423570985008687907853269984665640564039457584007913129639935, b = false\n\nc = 0\n\nTransaction trace:\nconstructor()\nState: a = 0, b = false\nf()\nState: a = 115792089237316195423570985008687907853269984665640564039457584007913129639935, b = false\nf() +// Warning 3944: (137-140): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\na = 0, b = false\n\nc = 0\n\nTransaction trace:\nconstructor()\nState: a = 0, b = false\nf() +// Warning 6328: (150-163): CHC: Assertion violation happens here.\nCounterexample:\na = 115792089237316195423570985008687907853269984665640564039457584007913129639935, b = false\n\nc = 0\n\nTransaction trace:\nconstructor()\nState: a = 0, b = false\nf() diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_array.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_array.sol index d2685dc4b..401e4af62 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_add_array.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_array.sol @@ -15,4 +15,4 @@ contract C } } // ---- -// Warning 6328: (240-253): CHC: Assertion violation happens here.\nCounterexample:\narray = []\nx = 38\n\n\nTransaction trace:\nconstructor()\nState: array = []\nf(38) +// Warning 6328: (240-253): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_mapping.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_mapping.sol index d4950a9b5..ac136acd2 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_add_mapping.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_mapping.sol @@ -14,5 +14,7 @@ contract C assert(b < 3); } } +// ==== +// SMTIgnoreCex: yes // ---- -// Warning 6328: (244-257): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 38\n\n\nTransaction trace:\nconstructor()\nf(38) +// Warning 6328: (244-257): CHC: Assertion violation happens here. diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_minus_overflow_detected.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_minus_overflow_detected.sol new file mode 100644 index 000000000..79ecefd42 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_minus_overflow_detected.sol @@ -0,0 +1,25 @@ +pragma experimental SMTChecker; +contract C { + uint8 x; + + function inc_pre() public { + ++x; + } + + function dec_pre() public { + --x; + } + + /* Commented out because Spacer segfaults in Z3 4.8.9 + function inc_post() public { + x++; + } + + function dec_post() public { + x--; + } + */ +} +// ---- +// Warning 4984: (87-90): CHC: Overflow (resulting value larger than 255) happens here.\nCounterexample:\nx = 255\n\n\n\nTransaction trace:\nconstructor()\nState: x = 0\ndec_pre()\nState: x = 255\ninc_pre() +// Warning 3944: (127-130): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\nx = 0\n\n\n\nTransaction trace:\nconstructor()\nState: x = 0\ndec_pre() diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly.sol new file mode 100644 index 000000000..c06b45196 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; + +contract C { + uint8 x = 254; + + function inc_pre() public { + ++x; + } + + function check() view public { + uint y = x; + assert(y < 256); + } +} +// ---- +// Warning 4984: (94-97): CHC: Overflow (resulting value larger than 255) happens here.\nCounterexample:\nx = 255\n\n\n\nTransaction trace:\nconstructor()\nState: x = 254\ninc_pre()\nState: x = 255\ninc_pre() diff --git a/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly_struct.sol b/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly_struct.sol new file mode 100644 index 000000000..35c835f8b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/unary_add_overflows_correctly_struct.sol @@ -0,0 +1,24 @@ +pragma experimental SMTChecker; + +contract C { + struct S { + uint8 x; + } + + S s; + + constructor() { + s.x = 254; + } + + function inc_pre() public { + ++s.x; + } + + function check() view public { + uint y = s.x; + assert(y < 256); + } +} +// ---- +// Warning 4984: (145-150): CHC: Overflow (resulting value larger than 255) happens here.\nCounterexample:\ns = {x: 255}\n\n\n\nTransaction trace:\nconstructor()\nState: s = {x: 254}\ninc_pre()\nState: s = {x: 255}\ninc_pre() diff --git a/test/libsolidity/smtCheckerTests/operators/unary_sub_array.sol b/test/libsolidity/smtCheckerTests/operators/unary_sub_array.sol index 008b7c117..0b5a6e59e 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_sub_array.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_sub_array.sol @@ -15,4 +15,4 @@ contract C } } // ---- -// Warning 6328: (240-253): CHC: Assertion violation happens here.\nCounterexample:\narray = []\nx = 38\n\n\nTransaction trace:\nconstructor()\nState: array = []\nf(38) +// Warning 6328: (240-253): CHC: Assertion violation happens here.\nCounterexample:\narray = []\nx = 0\n\n\nTransaction trace:\nconstructor()\nState: array = []\nf(0) diff --git a/test/libsolidity/smtCheckerTests/operators/unary_sub_mapping.sol b/test/libsolidity/smtCheckerTests/operators/unary_sub_mapping.sol index d02e2ea19..0c40ad544 100644 --- a/test/libsolidity/smtCheckerTests/operators/unary_sub_mapping.sol +++ b/test/libsolidity/smtCheckerTests/operators/unary_sub_mapping.sol @@ -15,4 +15,4 @@ contract C } } // ---- -// Warning 6328: (244-257): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 38\n\n\nTransaction trace:\nconstructor()\nf(38) +// Warning 6328: (244-257): CHC: Assertion violation happens here.\nCounterexample:\n\nx = 0\n\n\nTransaction trace:\nconstructor()\nf(0) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_recursive_6.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_recursive_6.sol index f61085e81..c165fb30f 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_recursive_6.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_recursive_6.sol @@ -52,6 +52,10 @@ contract C { // Warning 8364: (258-260): Assertion checker does not yet implement type struct C.S storage ref // Warning 7650: (271-275): Assertion checker does not yet support this expression. // Warning 8364: (271-273): Assertion checker does not yet implement type struct C.S storage ref +// Warning 4984: (132-138): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() +// Warning 4984: (142-148): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() +// Warning 3944: (165-171): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() +// Warning 3944: (175-181): CHC: Underflow (resulting value less than 0) happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() // Warning 4984: (200-208): CHC: Overflow (resulting value larger than 2**256 - 1) happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() // Warning 6328: (185-209): CHC: Assertion violation happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() // Warning 6328: (213-247): CHC: Assertion violation happens here.\nCounterexample:\n\n\n\n\nTransaction trace:\nconstructor()\nf() @@ -87,11 +91,3 @@ contract C { // Warning 8364: (258-260): Assertion checker does not yet implement type struct C.S storage ref // Warning 7650: (271-275): Assertion checker does not yet support this expression. // Warning 8364: (271-273): Assertion checker does not yet implement type struct C.S storage ref -// Warning 4144: (132-138): BMC: Underflow (resulting value less than 0) happens here. -// Warning 2661: (132-138): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (142-148): BMC: Underflow (resulting value less than 0) happens here. -// Warning 2661: (142-148): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (165-171): BMC: Underflow (resulting value less than 0) happens here. -// Warning 2661: (165-171): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. -// Warning 4144: (175-181): BMC: Underflow (resulting value less than 0) happens here. -// Warning 2661: (175-181): BMC: Overflow (resulting value larger than 2**256 - 1) happens here. diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_unary_add.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_unary_add.sol index 6ca5f6ace..b32ac2225 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_unary_add.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_unary_add.sol @@ -15,4 +15,4 @@ contract C { } } // ---- -// Warning 6328: (225-245): CHC: Assertion violation happens here.\nCounterexample:\n\ns1 = {x: 2, a: []}\ns2 = {x: 3, a: [5, 5, 5, 5, 5, 5]}\n\n\nTransaction trace:\nconstructor()\nf({x: 0, a: []}, {x: 3, a: [5, 5, 5, 5, 5, 5]}) +// Warning 6328: (225-245): CHC: Assertion violation happens here.\nCounterexample:\n\ns1 = {x: 2, a: []}\ns2 = {x: 3, a: [6, 6, 6, 6, 6, 6, 6]}\n\n\nTransaction trace:\nconstructor()\nf({x: 0, a: []}, {x: 3, a: [6, 6, 6, 6, 6, 6, 6]}) diff --git a/test/libsolidity/smtCheckerTests/types/struct/struct_unary_sub.sol b/test/libsolidity/smtCheckerTests/types/struct/struct_unary_sub.sol index cfb93983c..3dda683a8 100644 --- a/test/libsolidity/smtCheckerTests/types/struct/struct_unary_sub.sol +++ b/test/libsolidity/smtCheckerTests/types/struct/struct_unary_sub.sol @@ -16,4 +16,4 @@ contract C { } } // ---- -// Warning 6328: (240-260): CHC: Assertion violation happens here.\nCounterexample:\n\ns1 = {x: 98, a: []}\ns2 = {x: (- 38), a: [5, 5, 5, 5, 5, 5]}\n\n\nTransaction trace:\nconstructor()\nf({x: 0, a: []}, {x: (- 38), a: [5, 5, 5, 5, 5, 5]}) +// Warning 6328: (240-260): CHC: Assertion violation happens here.\nCounterexample:\n\ns1 = {x: 98, a: []}\ns2 = {x: 99, a: [6, 6, 6, 6, 6, 6, 6]}\n\n\nTransaction trace:\nconstructor()\nf({x: 0, a: []}, {x: 99, a: [6, 6, 6, 6, 6, 6, 6]}) diff --git a/test/libsolidity/smtCheckerTests/types/unused_mapping.sol b/test/libsolidity/smtCheckerTests/types/unused_mapping.sol index f12cd41de..01905a36e 100644 --- a/test/libsolidity/smtCheckerTests/types/unused_mapping.sol +++ b/test/libsolidity/smtCheckerTests/types/unused_mapping.sol @@ -12,6 +12,7 @@ contract C { if(x == 0) x = 0; // noop state var read x++; y++; - assert(y == x); + // Commented out because of nondeterminism in Spacer in Z3 4.8.9 + //assert(y == x); } } From 2481f2c6bb748a5f9f2bcf8958bd6f5446318c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 01:02:22 +0100 Subject: [PATCH 18/29] common_cmdline.sh: Fix misspelled $args --- scripts/common_cmdline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 1d21fe75c..38b9996f5 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -71,7 +71,7 @@ function compileFull() printError "Was failure: $exit_code" echo "$errors" printError "While calling:" - echo "\"$SOLC\" $ARGS $files" + echo "\"$SOLC\" $args $files" printError "Inside directory:" pwd false From 74b5560f7e0af3100a7122bdd2fe9cc90f9c06b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 11 Dec 2020 18:49:13 +0100 Subject: [PATCH 19/29] docs_version_pragma_check.sh: Fix broken variable comparison hiding missing compiler version warnings --- scripts/docs_version_pragma_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index 520be3e5e..264d7baf3 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -117,7 +117,7 @@ function findMinimalVersion() fi done - if [ -z version ] + if [ -z "$version" ] then printError "No release $sign$pragmaVersion was listed in available releases!" fi From 784871c424989712ead10afee93692a1acf6d024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 04:29:20 +0100 Subject: [PATCH 20/29] docs_version_pragma_check.sh: Get binaries from soliditylang.org, not github.io --- scripts/docs_version_pragma_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index 264d7baf3..f26355b47 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -65,7 +65,7 @@ function getAllAvailableVersions() { allVersions=() local allListedVersions=( $( - wget -q -O- https://ethereum.github.io/solc-bin/bin/list.txt | + wget -q -O- https://binaries.soliditylang.org/bin/list.txt | grep -Po '(?<=soljson-v)\d+.\d+.\d+(?=\+commit)' | sort -V ) ) From 6fc45b3e022e2a1691854765de9ed2717c96c2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 04:32:22 +0100 Subject: [PATCH 21/29] docs_version_pragma_check.sh: Fix bad variable name making the script skip ^ and >= pragmas --- scripts/docs_version_pragma_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index f26355b47..2afdc29e7 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -108,7 +108,7 @@ function findMinimalVersion() do if versionGreater "$ver" "$pragmaVersion" then - minVersion="$ver" + version="$ver" break elif ([ $greater == false ]) && versionEqual "$ver" "$pragmaVersion" then From 304b2fe2323795946ef81f1947a8e0e1fbcc509e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 04:45:17 +0100 Subject: [PATCH 22/29] docs_version_pragma_check.sh: Fail when there is no matching release --- scripts/docs_version_pragma_check.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/docs_version_pragma_check.sh b/scripts/docs_version_pragma_check.sh index 2afdc29e7..458c55308 100755 --- a/scripts/docs_version_pragma_check.sh +++ b/scripts/docs_version_pragma_check.sh @@ -120,6 +120,7 @@ function findMinimalVersion() if [ -z "$version" ] then printError "No release $sign$pragmaVersion was listed in available releases!" + exit 1 fi } From 0f6f4314b6e49f67af8db68e12b60fd72d0eb2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 04:35:17 +0100 Subject: [PATCH 23/29] Fix code snippets in docs not passing tests on versions matching their pragmas --- docs/contracts/constant-state-variables.rst | 2 +- docs/introduction-to-smart-contracts.rst | 2 +- docs/natspec-format.rst | 2 +- docs/style-guide.rst | 4 ++++ docs/types/reference-types.rst | 4 ++-- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/contracts/constant-state-variables.rst b/docs/contracts/constant-state-variables.rst index fa1fd8c92..d22735618 100644 --- a/docs/contracts/constant-state-variables.rst +++ b/docs/contracts/constant-state-variables.rst @@ -30,7 +30,7 @@ Not all types for constants and immutables are implemented at this time. The onl :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >0.7.2; + pragma solidity >=0.7.4; uint constant X = 32**22 + 8; diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index f2b12e930..2c06fdf87 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -83,7 +83,7 @@ registering with a username and password, all you need is an Ethereum keypair. :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >0.5.99 <0.8.0; + pragma solidity >=0.7.0 <0.8.0; contract Coin { // The keyword "public" makes variables diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 21e78f2df..0ff94430d 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -49,7 +49,7 @@ The following example shows a contract and a function using all available tags. .. code:: Solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >0.6.10 <0.8.0; + pragma solidity >=0.6.12 <0.8.0; /// @title A simulator for trees /// @author Larry A. Gardner diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 6964b978a..b7f27da7f 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -1071,6 +1071,10 @@ No:: and in ``Congress.sol``:: + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.7.0; + + import "./owned.sol"; diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 7157d88c6..2022694b9 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -243,7 +243,7 @@ individual elements: :: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.8.0; + pragma solidity >=0.4.16 <0.8.0; contract C { function f() public pure { @@ -554,4 +554,4 @@ assigning it to a local variable, as in .. note:: Until Solidity 0.7.0, memory-structs containing members of storage-only types (e.g. mappings) were allowed and assignments like ``campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0)`` - in the example above would work and just silently skip those members. \ No newline at end of file + in the example above would work and just silently skip those members. From 1f2ffa99c242d0c40da31f4b1e6fed497e75becb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 05:40:20 +0100 Subject: [PATCH 24/29] cmdlineTests.sh: Fix test_solc_assembly_output including garbage in the tested output --- test/cmdlineTests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 86fb66670..5420d5f59 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -206,7 +206,7 @@ function test_solc_assembly_output() local expected_object="object \"object\" { code "${expected}" }" output=$(echo "${input}" | "$SOLC" - ${solc_args} 2>/dev/null) - empty=$(echo $output | sed -ne '/'"${expected_object}"'/p') + empty=$(echo "$output" | tr '\n' ' ' | tr -s ' ' | sed -ne "/${expected_object}/p") if [ -z "$empty" ] then printError "Incorrect assembly output. Expected: " From ac12274acd289ea2c3715619bb0d03e9d0c8919e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 05:49:06 +0100 Subject: [PATCH 25/29] cmdlineTests.sh: Fix the script failing to detect that --ast option does not exist --- test/cmdlineTests.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 5420d5f59..2dedbafe7 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -436,15 +436,18 @@ SOLTMPDIR=$(mktemp -d) # The contract should be compiled if [[ "$result" != 0 ]] then + printError "Failed to compile a simple contract from standard input" exit 1 fi # This should not fail set +e - output=$(echo '' | "$SOLC" --ast - 2>/dev/null) + output=$(echo '' | "$SOLC" --ast-json - 2>/dev/null) + result=$? set -e - if [[ $? != 0 ]] + if [[ $result != 0 ]] then + printError "Incorrect response to --ast-json option with empty stdin" exit 1 fi ) From 81668eb26a9d27b2ef29d7e0d6b663e00de519c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 11 Dec 2020 20:02:04 +0100 Subject: [PATCH 26/29] soltest_all: Fix an error being printed to a file called `2` rather than to stderr --- .circleci/soltest_all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 8281131b8..a88513aca 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -80,6 +80,6 @@ done if (($STEP != $STEPS + 1)) then - echo "Step counter not properly adjusted!" >2 + echo "Step counter not properly adjusted!" >&2 exit 1 fi From f712662a663e98733f9ad33ed141a25558921db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 01:23:27 +0100 Subject: [PATCH 27/29] ASTImportTest.sh: Fix the script ignoring all but the first file from a multi-source test when testing input equivalence --- scripts/ASTImportTest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ASTImportTest.sh b/scripts/ASTImportTest.sh index 02125c921..350b8251c 100755 --- a/scripts/ASTImportTest.sh +++ b/scripts/ASTImportTest.sh @@ -98,7 +98,7 @@ do NSOURCES=$((NSOURCES - 1)) for i in $OUTPUT; do - testImportExportEquivalence $i $OUTPUT + testImportExportEquivalence "$i" "$OUTPUT" NSOURCES=$((NSOURCES + 1)) done elif [ ${SPLITSOURCES_RC} == 1 ] From 893a5b6e60fb8aedb882f9b2c90faed518cab287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 11 Dec 2020 19:22:06 +0100 Subject: [PATCH 28/29] Remove unused variables --- .circleci/soltest.sh | 1 - scripts/common_cmdline.sh | 1 - scripts/install_cmake.sh | 1 - scripts/release_ppa.sh | 1 - scripts/tests.sh | 4 ++-- scripts/wasm-rebuild/docker-scripts/patch.sh | 7 ++++--- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index 3eb15d051..a974386f9 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -36,7 +36,6 @@ set -e OPTIMIZE=${OPTIMIZE:-"0"} EVM=${EVM:-"invalid"} -WORKDIR=${CIRCLE_WORKING_DIRECTORY:-.} REPODIR="$(realpath $(dirname $0)/..)" source "${REPODIR}/scripts/common.sh" diff --git a/scripts/common_cmdline.sh b/scripts/common_cmdline.sh index 1d21fe75c..33943d80f 100644 --- a/scripts/common_cmdline.sh +++ b/scripts/common_cmdline.sh @@ -49,7 +49,6 @@ function compileFull() fi local files="$*" - local output local stderr_path=$(mktemp) diff --git a/scripts/install_cmake.sh b/scripts/install_cmake.sh index 134b86f09..64647645e 100755 --- a/scripts/install_cmake.sh +++ b/scripts/install_cmake.sh @@ -27,7 +27,6 @@ if test -f $BIN/cmake && ($BIN/cmake --version | grep -q "$VERSION"); then else FILE=cmake-$VERSION-$OS-x86_64.tar.gz URL=https://cmake.org/files/v$VERSION_MAJOR.$VERSION_MINOR/$FILE - ERROR=0 TMPFILE=$(mktemp --tmpdir cmake-$VERSION-$OS-x86_64.XXXXXXXX.tar.gz) echo "Downloading CMake ($URL)..." wget "$URL" -O "$TMPFILE" -nv diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 5cc83c020..0a1ef62c4 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -113,7 +113,6 @@ wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-sourc cd solc version=$($(dirname "$0")/get_version.sh) commithash=$(git rev-parse --short=8 HEAD) -committimestamp=$(git show --format=%ci HEAD | head -n 1) commitdate=$(git show --format=%ci HEAD | head -n 1 | cut - -b1-10 | sed -e 's/-0?/./' | sed -e 's/-0?/./') echo "$commithash" > commit_hash.txt diff --git a/scripts/tests.sh b/scripts/tests.sh index 11191c86e..f5894471f 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -109,9 +109,9 @@ do then if [ -n "$optimize" ] then - log=--logger=JUNIT,error,$log_directory/opt_$vm.xml $testargs + log=--logger=JUNIT,error,$log_directory/opt_$vm.xml else - log=--logger=JUNIT,error,$log_directory/noopt_$vm.xml $testargs_no_opt + log=--logger=JUNIT,error,$log_directory/noopt_$vm.xml fi fi diff --git a/scripts/wasm-rebuild/docker-scripts/patch.sh b/scripts/wasm-rebuild/docker-scripts/patch.sh index a03fc73d0..0c536b46c 100755 --- a/scripts/wasm-rebuild/docker-scripts/patch.sh +++ b/scripts/wasm-rebuild/docker-scripts/patch.sh @@ -1,7 +1,8 @@ #!/bin/bash -TAG="$1" -SOLJSON_JS="$2" - # If we ever want to patch the binaries e.g. for compatibility with older solc-js versions, # we can do that here. +# +# This script gets the following parameters: +# - TAG +# - SOLJSON_JS From 4a16b13a571238aeaf8662e7421232f7fc6adc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Sat, 12 Dec 2020 07:49:54 +0100 Subject: [PATCH 29/29] get_version.sh: Quote the ? wildcard that could otherwise break the regex in the presence of a single-letter file name --- scripts/get_version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/get_version.sh b/scripts/get_version.sh index b2abc6e34..a47cda619 100755 --- a/scripts/get_version.sh +++ b/scripts/get_version.sh @@ -28,4 +28,4 @@ set -e -grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")"? $(dirname "$0")/../CMakeLists.txt +grep -oP "PROJECT_VERSION \"?\K[0-9.]+(?=\")?" $(dirname "$0")/../CMakeLists.txt