From f2c0ef750e243d51eed9aeb0ac11bbeed60d721c Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 14 Apr 2021 18:37:48 +0200 Subject: [PATCH] Fuzz Yul optimizer with stack pressure. --- .../ossfuzz/YulToEvmDifferentialFuzzer.cpp | 48 ++++++++++--------- test/tools/ossfuzz/protoToYul.cpp | 8 ++-- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/test/tools/ossfuzz/YulToEvmDifferentialFuzzer.cpp b/test/tools/ossfuzz/YulToEvmDifferentialFuzzer.cpp index d8b918383..854b9d365 100644 --- a/test/tools/ossfuzz/YulToEvmDifferentialFuzzer.cpp +++ b/test/tools/ossfuzz/YulToEvmDifferentialFuzzer.cpp @@ -100,16 +100,15 @@ DEFINE_PROTO_FUZZER(Program const& _input) of.write(yul_source.data(), static_cast(yul_source.size())); } - solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::none(); - // Stack evader requires stack allocation to be done. - settings.optimizeStackAllocation = true; - settings.runYulOptimiser = true; - AssemblyStack stackUnoptimized(version, AssemblyStack::Language::StrictAssembly, settings); + AssemblyStack stackUnoptimized( + version, + AssemblyStack::Language::StrictAssembly, + solidity::frontend::OptimiserSettings::none() + ); solAssert( stackUnoptimized.parseAndAnalyze("source", yulSubObject), "Parsing fuzzer generated input failed." ); - stackUnoptimized.optimize(); ostringstream unoptimizedState; yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( unoptimizedState, @@ -123,21 +122,17 @@ DEFINE_PROTO_FUZZER(Program const& _input) if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) return; - AssemblyStack stackOptimized(version, AssemblyStack::Language::StrictAssembly, settings); + AssemblyStack stackOptimized( + version, + AssemblyStack::Language::StrictAssembly, + solidity::frontend::OptimiserSettings::standard() + ); solAssert( stackOptimized.parseAndAnalyze("source", yulSubObject), "Parsing fuzzer generated input failed." ); stackOptimized.optimize(); - YulOptimizerTestCommon optimizerTest( - stackOptimized.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version) - ); - // HACK: Force this to fake stack limit evader for now - string step = "stackLimitEvader"; - optimizerTest.setStep(step); -// optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); - shared_ptr astBlock = optimizerTest.run(); + string optObject = AsmPrinter{}(*stackOptimized.parserResult()->code); string optimisedProgram = Whiskers(R"( object "main" { code { @@ -151,12 +146,20 @@ DEFINE_PROTO_FUZZER(Program const& _input) } } )") - ("fuzzerInput", AsmPrinter{}(*astBlock)) + ("fuzzerInput", optObject) .render(); - cout << AsmPrinter{}(*astBlock) << endl; + cout << optObject << endl; bytes optimisedByteCode; - settings.runYulOptimiser = false; - optimisedByteCode = YulAssembler{version, settings, optimisedProgram}.assemble(); + solidity::frontend::OptimiserSettings s = solidity::frontend::OptimiserSettings::none(); + s.optimizeStackAllocation = true; + try + { + optimisedByteCode = YulAssembler{version, s, optimisedProgram}.assemble(); + } + catch (yul::StackTooDeepError const&) + { + return; + } // Reset host before running optimised code. hostContext.reset(); @@ -167,6 +170,9 @@ DEFINE_PROTO_FUZZER(Program const& _input) ); auto callMessageOpt = YulEvmoneUtility{}.callMessage(deployResultOpt.create_address); evmc::result callResultOpt = hostContext.call(callMessageOpt); + // Bail out if we ran out of gas. + if (callResultOpt.status_code == EVMC_OUT_OF_GAS) + return; bool noRevertInSource = yulSubObject.find("revert") == string::npos; bool noInvalidInSource = yulSubObject.find("invalid") == string::npos; if (noRevertInSource) @@ -185,8 +191,6 @@ DEFINE_PROTO_FUZZER(Program const& _input) (!noInvalidInSource && callResultOpt.status_code == EVMC_INVALID_INSTRUCTION)), "Optimised call failed." ); - if (callResultOpt.status_code == EVMC_OUT_OF_GAS) - return; ostringstream optimizedState; optimizedState << EVMHostPrinter{hostContext, deployResultOpt.create_address}.storageOnly(); diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 708e18caf..ee21cbd58 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -573,7 +573,8 @@ void ProtoConverter::visit(UnaryOp const& _x) op == UnaryOp::EXTCODEHASH || op == UnaryOp::EXTCODESIZE || op == UnaryOp::BALANCE || - op == UnaryOp::BLOCKHASH + op == UnaryOp::BLOCKHASH || + op == UnaryOp::MLOAD ) ) { @@ -659,7 +660,8 @@ void ProtoConverter::visit(NullaryOp const& _x) op == NullaryOp::TIMESTAMP || op == NullaryOp::NUMBER || op == NullaryOp::CHAINID || - op == NullaryOp::SELFBALANCE + op == NullaryOp::SELFBALANCE || + op == NullaryOp::MSIZE ) ) { @@ -1724,7 +1726,7 @@ void ProtoConverter::fillFunctionCallInput(unsigned _numInParams) m_output << "calldataload(" << slot << ")"; break; case 1: - m_output << "mload(" << slot << ")"; + m_output << "sload(" << slot << ")"; break; case 2: m_output << "sload(" << slot << ")";