diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 89acd2c09..410541a9d 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -59,25 +59,41 @@ DEFINE_PROTO_FUZZER(Program const& _input) filterStatefulInstructions, filterUnboundedLoops ); - string yul_source = converter.programToString(_input); + string yulSubObject = converter.programToString(_input); // Fuzzer also fuzzes the EVM version field. langutil::EVMVersion version = converter.version(); EVMHost hostContext(version, evmone); hostContext.reset(); + // Do not proceed with tests that are too large. 1200 is an arbitrary + // threshold. + if (yulSubObject.size() > 1200) + return; + + YulStringRepository::reset(); + + // Package test case into a sub-object + solidity::util::Whiskers yulObjectFormat(R"( +object "main" { + code { + codecopy(0, dataoffset("deployed"), datasize("deployed")) + return(0, datasize("deployed")) + } + object "deployed" { + code { + + } + } +} + )"); + string yul_source = yulObjectFormat("fuzzerInput", yulSubObject).render(); + if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { ofstream of(dump_path); of.write(yul_source.data(), static_cast(yul_source.size())); } - // Do not proceed with tests that are too large. 1200 is an arbitrary - // threshold. - if (yul_source.size() > 1200) - return; - - YulStringRepository::reset(); - solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::full(); settings.runYulOptimiser = false; settings.optimizeStackAllocation = false; @@ -93,7 +109,10 @@ DEFINE_PROTO_FUZZER(Program const& _input) evmc::result deployResult = YulEvmoneUtility{}.deployCode(unoptimisedByteCode, hostContext); if (deployResult.status_code != EVMC_SUCCESS) + { + cout << "Deploy unoptimised failed." << endl; return; + } auto callMessage = YulEvmoneUtility{}.callMessage(deployResult.create_address); evmc::result callResult = hostContext.call(callMessage); // If the fuzzer synthesized input does not contain the revert opcode which @@ -112,13 +131,17 @@ DEFINE_PROTO_FUZZER(Program const& _input) ); // Bail out on serious errors encountered during a call. if (YulEvmoneUtility{}.seriousCallError(callResult.status_code)) + { + cout << "Unoptimised call failed." << endl; return; + } solAssert( (callResult.status_code == EVMC_SUCCESS || (!noRevertInSource && callResult.status_code == EVMC_REVERT) || (!noInvalidInSource && callResult.status_code == EVMC_INVALID_INSTRUCTION)), "Unoptimised call failed." ); + ostringstream unoptimizedState; unoptimizedState << EVMHostPrinter{hostContext, deployResult.create_address}.state(); @@ -162,18 +185,11 @@ DEFINE_PROTO_FUZZER(Program const& _input) ostringstream optimizedState; optimizedState << EVMHostPrinter{hostContext, deployResultOpt.create_address}.state(); - int64_t constexpr tolerance = 1000; - if (callResult.gas_left > callResultOpt.gas_left) - if (callResult.gas_left - callResultOpt.gas_left > tolerance) - { - cout << "Gas differential " << callResult.gas_left - callResultOpt.gas_left << endl; - cout << "Unoptimised bytecode" << endl; - cout << util::toHex(unoptimisedByteCode) << endl; - cout << "Optimised bytecode" << endl; - cout << util::toHex(optimisedByteCode) << endl; - solAssert(false, "Optimised code consumed more than +1000 gas."); - } - + if (unoptimizedState.str() != optimizedState.str()) + { + cout << unoptimizedState.str() << endl; + cout << optimizedState.str() << endl; + } solAssert( unoptimizedState.str() == optimizedState.str(), "State of unoptimised and optimised stack reused code do not match." diff --git a/test/tools/ossfuzz/YulEvmoneInterface.cpp b/test/tools/ossfuzz/YulEvmoneInterface.cpp index fe737993d..a4f095d8e 100644 --- a/test/tools/ossfuzz/YulEvmoneInterface.cpp +++ b/test/tools/ossfuzz/YulEvmoneInterface.cpp @@ -48,24 +48,8 @@ evmc::result YulEvmoneUtility::deployCode(bytes const& _input, EVMHost& _host) _input.size() <= 0xffff, "Deployed byte code is larger than the permissible 65535 bytes." ); - uint8_t inputSizeHigher = static_cast(_input.size() >> 8); - uint8_t inputSizeLower = _input.size() & 0xff; - /* - * CODESIZE - * PUSH0 0xc - * PUSH0 0x0 - * CODECOPY - * PUSH1 - * PUSH0 0x0 - * RETURN - */ - bytes deployCode = bytes{ - 0x38, 0x60, 0x0c, 0x60, 0x00, 0x39, 0x61, - inputSizeHigher, inputSizeLower, - 0x60, 0x00, 0xf3 - } + _input; - msg.input_data = deployCode.data(); - msg.input_size = deployCode.size(); + msg.input_data = _input.data(); + msg.input_size = _input.size(); msg.kind = EVMC_CREATE; return _host.call(msg); }