diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp index 5c2e44f44..a906728d0 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.cpp +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.cpp @@ -154,30 +154,39 @@ evmc::result EvmoneUtility::deployAndExecute( return callResult; } +optional EvmoneUtility::compileAndDeployLibrary() +{ + solAssert(!m_libraryName.empty(), "SolidityEvmoneInterface: No library set."); + m_compilationFramework.contractName(m_libraryName); + auto compilationOutput = m_compilationFramework.compileContract(); + m_compilationFramework.contractName(m_contractName); + if (compilationOutput.has_value()) + { + CompilerOutput cOutput = compilationOutput.value(); + // Deploy contract and signal failure if deploy failed + evmc::result createResult = deployContract(cOutput.byteCode); + solAssert( + createResult.status_code == EVMC_SUCCESS, + "SolidityEvmoneInterface: Library deployment failed" + ); + m_compilationFramework.libraryAddresses( + {{m_libraryName, EVMHost::convertFromEVMC(createResult.create_address)}} + ); + return createResult; + } + else + return nullopt; +} + optional EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) { - map libraryAddressMap; - // Stage 1: Compile and deploy library if present. + // Stage 1: Deploy library if it exists. if (!m_libraryName.empty()) { - m_compilationFramework.contractName(m_libraryName); - auto compilationOutput = m_compilationFramework.compileContract(); - if (compilationOutput.has_value()) - { - CompilerOutput cOutput = compilationOutput.value(); - // Deploy contract and signal failure if deploy failed - evmc::result createResult = deployContract(cOutput.byteCode); - solAssert( - createResult.status_code == EVMC_SUCCESS, - "SolidityEvmoneInterface: Library deployment failed" - ); - libraryAddressMap[m_libraryName] = EVMHost::convertFromEVMC(createResult.create_address); - m_compilationFramework.libraryAddresses(libraryAddressMap); - } - else - return {}; + auto r = compileAndDeployLibrary(); + if (!r.has_value()) + return r; } - // Stage 2: Compile, deploy, and execute contract, optionally using library // address map. m_compilationFramework.contractName(m_contractName); diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index aaaacda5c..e6163c4af 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -218,6 +218,9 @@ public: /// identifiers for methods in @param _contractName. std::optional compileContract(); + /// Compiles and deploys library on blockchain. + std::optional compileAndDeployLibrary(); + private: /// EVM Host implementation diff --git a/test/tools/ossfuzz/solc_ossfuzz.cpp b/test/tools/ossfuzz/solc_ossfuzz.cpp index ca5e3e997..c9ba40d48 100644 --- a/test/tools/ossfuzz/solc_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_ossfuzz.cpp @@ -34,6 +34,7 @@ #include +#include #include using namespace solidity::frontend::test; @@ -54,9 +55,12 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) // if (_size <= 600) { string input(reinterpret_cast(_data), _size); - // TODO: Cannot fuzz tests containing libraries yet. - if (input.find("library") != string::npos) - return 0; + regex re = regex("library\\s*(\\w+)\\s*\\{"); + smatch matches; + std::string libraryName; + auto match = regex_search(input, matches, re); + if (match && matches[1].matched) + libraryName = matches[1].str(); map sourceCode; try @@ -82,10 +86,22 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) hostContext, cInput, contractName, - {}, + libraryName, methodName ); + if (!libraryName.empty()) + { + cout << "Deploying library" << endl; + auto l = evmoneUtil.compileAndDeployLibrary(); + if (!l.has_value()) + return 0; + cout << "Deployed" << endl; + } + + hostContext.reset(); + evmoneUtil.reset(true); + evmoneUtil.optSetting(compilerSetting); auto compilerOutput = evmoneUtil.compileContract(); if (!compilerOutput.has_value()) return 0;