diff --git a/test/tools/ossfuzz/SolidityEvmoneInterface.h b/test/tools/ossfuzz/SolidityEvmoneInterface.h index 52f35a78a..fa398f7b2 100644 --- a/test/tools/ossfuzz/SolidityEvmoneInterface.h +++ b/test/tools/ossfuzz/SolidityEvmoneInterface.h @@ -105,6 +105,18 @@ public: { return m_compiler.lastContractName(); } + void optSetting(frontend::OptimiserSettings _opt) + { + m_compilerInput.optimiserSettings = _opt; + } + void source(StringMap const& _source) + { + m_compilerInput.sourceCode = _source; + } + void reset(bool _keepSettings) + { + m_compiler.reset(_keepSettings); + } private: frontend::CompilerStack m_compiler; CompilerInput m_compilerInput; @@ -158,10 +170,22 @@ public: m_contractName = m_compilationFramework.lastContractName(); m_compilationFramework.contractName(m_contractName); } + void source(StringMap const& _source) + { + m_compilationFramework.source(_source); + } + void reset(bool _keepSettings) + { + m_compilationFramework.reset(_keepSettings); + } std::optional noInputFunction() { return m_compilationFramework.noInputFunction(); } + void optSetting(frontend::OptimiserSettings _opt) + { + m_compilationFramework.optSetting(_opt); + } /// @returns the result of the execution of the function whose /// keccak256 hash is @param _functionHash that is deployed at diff --git a/test/tools/ossfuzz/solc_ossfuzz.cpp b/test/tools/ossfuzz/solc_ossfuzz.cpp index dcc9bd6cf..a65da271f 100644 --- a/test/tools/ossfuzz/solc_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_ossfuzz.cpp @@ -91,8 +91,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) if (deployResult.status_code != EVMC_SUCCESS) return 0; + auto methodSig = solidity::util::fromHex(compilerOutput->methodIdentifiersInContract[noInputFunction.value()].asString()); auto callResult = evmoneUtil.executeContract( - solidity::util::fromHex(compilerOutput->methodIdentifiersInContract[noInputFunction.value()].asString()), + methodSig, deployResult.create_address ); @@ -104,6 +105,50 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) result.push_back(callResult.output_data[i]); cout << solidity::util::toHex(result) << endl; + + EVMHostPrinter p(hostContext, deployResult.create_address); + ostringstream oldCodeGen; + oldCodeGen << p.state(); + + compilerSetting.runYulOptimiser = true; + compilerSetting.optimizeStackAllocation = true; + CompilerInput cInputOpt = { + version, + sourceCode, + contractName, + compilerSetting, + {}, + false, + true + }; + hostContext.reset(); + evmoneUtil.reset(true); + evmoneUtil.optSetting(compilerSetting); + auto compilerOutputOpt = evmoneUtil.compileContract(); + solAssert(compilerOutputOpt.has_value(), "Contract could not be optimised."); + + auto deployResultOpt = evmoneUtil.deployContract(compilerOutputOpt->byteCode); + solAssert(deployResultOpt.status_code == EVMC_SUCCESS, "Contract compiled via new code gen could not be deployed."); + + auto callResultOpt = evmoneUtil.executeContract( + methodSig, + deployResultOpt.create_address + ); + solAssert(callResultOpt.status_code == EVMC_SUCCESS, "New code gen contract call failed."); + + solidity::bytes resultOpt; + for (size_t i = 0; i < callResultOpt.output_size; i++) + resultOpt.push_back(callResultOpt.output_data[i]); + + cout << solidity::util::toHex(resultOpt) << endl; + solAssert(result == resultOpt, "Old and new code gen call results do not match."); + + EVMHostPrinter pOpt(hostContext, deployResultOpt.create_address); + ostringstream newCodeGen; + newCodeGen << pOpt.state(); + + solAssert(oldCodeGen.str() == newCodeGen.str(), "Old and new code gen state do not match."); + return 0; } catch (runtime_error const&) {