diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 456637cd6..eaaa1f0fb 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -44,6 +44,7 @@ struct InternalCompilerError: virtual util::Exception {}; struct FatalError: virtual util::Exception {}; struct UnimplementedFeatureError: virtual util::Exception {}; struct InvalidAstError: virtual util::Exception {}; +struct TestFrameworkError: virtual util::Exception {}; /// Assertion that throws an InternalCompilerError containing the given description if it is not met. #define solAssert(CONDITION, DESCRIPTION) \ diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index d6912c5d0..412d7aa38 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -37,13 +38,6 @@ #include -#include - -namespace solidity::frontend::test -{ -struct LogRecord; -} // namespace solidity::frontend::test - namespace solidity::test { using rational = boost::rational; @@ -84,8 +78,8 @@ public: _arguments, _libraryAddresses ); - BOOST_REQUIRE(m_transactionSuccessful); - BOOST_REQUIRE(!m_output.empty()); + assertThrow(m_transactionSuccessful, langutil::TestFrameworkError, ""); + assertThrow(!m_output.empty(), langutil::TestFrameworkError, ""); return m_output; } @@ -135,8 +129,9 @@ public: { bytes contractResult = callContractFunction(_sig, _arguments...); bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); - BOOST_CHECK_MESSAGE( + assertThrow( contractResult == cppResult, + langutil::TestFrameworkError, "Computed values do not match.\nContract: " + util::toHex(contractResult) + "\nC++: " + @@ -151,8 +146,9 @@ public: { bytes contractResult = callContractFunction(_sig, argument); bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); - BOOST_CHECK_MESSAGE( + assertThrow( contractResult == cppResult, + langutil::TestFrameworkError, "Computed values do not match.\nContract: " + util::toHex(contractResult) + "\nC++: " + @@ -311,7 +307,11 @@ protected: #define ABI_CHECK(result, expectation) do { \ auto abiCheckResult = ExecutionFramework::compareAndCreateMessage((result), (expectation)); \ - BOOST_CHECK_MESSAGE(abiCheckResult.first, abiCheckResult.second); \ + assertThrow( \ + abiCheckResult.first == abiCheckResult.second, \ + langutil::TestFrameworkError, \ + ""\ + ); \ } while (0) diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index 2703ff441..85e5ad40f 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -124,7 +124,9 @@ bool isFixedTupleArray(string const& _type) return regex_match(_type, regex{"tuple\\[\\d+\\]"}); } -string functionSignatureFromABI(Json::Value const& _functionABI) +} + +string ContractABIUtils::functionSignatureFromABI(Json::Value const& _functionABI) { auto inputs = _functionABI["inputs"]; string signature = {_functionABI["name"].asString() + "("}; @@ -141,8 +143,6 @@ string functionSignatureFromABI(Json::Value const& _functionABI) return signature + ")"; } -} - std::optional ContractABIUtils::parametersFromJsonOutputs( ErrorReporter& _errorReporter, Json::Value const& _contractABI, diff --git a/test/libsolidity/util/ContractABIUtils.h b/test/libsolidity/util/ContractABIUtils.h index 209eca423..7929c49ba 100644 --- a/test/libsolidity/util/ContractABIUtils.h +++ b/test/libsolidity/util/ContractABIUtils.h @@ -75,6 +75,9 @@ public: /// on the size of their types. static size_t encodingSize(ParameterList const& _paremeters); + /// @returns function signature from ABI. + static std::string functionSignatureFromABI(Json::Value const& _functionABI); + private: /// Parses and translates a single type and returns a list of /// internal type representations of isoltest. diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index 7c5b4f024..b97942847 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -29,6 +29,7 @@ if (OSSFUZZ) ../../TestCaseReader.cpp ../../EVMHost.cpp SolidityEvmoneInterface.cpp + ../../libsolidity/util/ContractABIUtils.cpp ) target_link_libraries(solc_ossfuzz PRIVATE libsolc evmasm evmc evmone-standalone) set_target_properties(solc_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 9ca5bdf5a..700deb984 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -23,6 +23,7 @@ #include #include +#include using namespace solidity::test::fuzzer; using namespace solidity::frontend; @@ -74,6 +75,20 @@ optional SolidityCompilationFramework::noInputFunction() return {}; } +optional SolidityCompilationFramework::randomFunction() +{ + Json::Value const& contractABI = m_compiler.contractABI(m_compiler.lastContractName()); + unsigned numFunctions = contractABI.size(); + if (numFunctions == 0) + return {}; + else + { + uniform_int_distribution d(0, contractABI.size()); + minstd_rand r(contractABI.size()); + return contractABI[d(r)]; + } +} + bool EvmoneUtility::zeroWord(uint8_t const* _result, size_t _length) { return _length == 32 && diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index 3b576fc27..94e899a53 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -100,6 +100,9 @@ public: /// @returns name of a public/external method that does not contain /// input parameters in its signature. std::optional noInputFunction(); + /// @returns FunctionABI of a randomly chosen external function in + /// current contract. + std::optional randomFunction(); /// @returns name of the last contract in source unit. std::string lastContractName() { @@ -178,6 +181,10 @@ public: { return m_compilationFramework.noInputFunction(); } + std::optional randomFunction() + { + return m_compilationFramework.randomFunction(); + } void optSetting(frontend::OptimiserSettings _opt) { m_compilationFramework.optSetting(_opt); diff --git a/test/tools/ossfuzz/solc_ossfuzz.cpp b/test/tools/ossfuzz/solc_ossfuzz.cpp index bfc599f33..42ca5ed24 100644 --- a/test/tools/ossfuzz/solc_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_ossfuzz.cpp @@ -22,6 +22,8 @@ #include +#include + #include #include @@ -84,6 +86,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) return 0; optional noInputFunction = evmoneUtil.noInputFunction(); + if (auto r = evmoneUtil.randomFunction(); r.has_value()) + cout << ContractABIUtils{}.functionSignatureFromABI(r.value()) << endl; if (noInputFunction.has_value()) evmoneUtil.methodName(noInputFunction.value()); else