mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6631 from ethereum/dataForInterpreter
Implement datasize, dataoffset and datacopy for yul interpreter.
This commit is contained in:
commit
601439687e
@ -132,7 +132,8 @@ string YulInterpreterTest::interpret()
|
||||
state.maxTraceSize = 10000;
|
||||
state.maxSteps = 10000;
|
||||
state.maxMemSize = 0x20000000;
|
||||
Interpreter interpreter(state);
|
||||
shared_ptr<Dialect> dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}));
|
||||
Interpreter interpreter(state, *dialect);
|
||||
try
|
||||
{
|
||||
interpreter(*m_ast);
|
||||
|
@ -30,7 +30,6 @@ namespace yul
|
||||
{
|
||||
struct AsmAnalysisInfo;
|
||||
struct Block;
|
||||
struct Dialect;
|
||||
}
|
||||
|
||||
namespace yul
|
||||
|
114
test/libyul/yulInterpreterTests/datacopy.yul
Normal file
114
test/libyul/yulInterpreterTests/datacopy.yul
Normal file
@ -0,0 +1,114 @@
|
||||
object "main"
|
||||
{
|
||||
code {
|
||||
datacopy(0, dataoffset("main"), datasize("main"))
|
||||
datacopy(32, dataoffset("sub"), datasize("sub"))
|
||||
sstore(0, mload(0))
|
||||
sstore(1, mload(32))
|
||||
}
|
||||
object "sub" { code { sstore(0, 1) } }
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// MSTORE_AT_SIZE(0, 2916)
|
||||
// MSTORE_AT_SIZE(32, 265)
|
||||
// MLOAD_FROM_SIZE(0, 32)
|
||||
// SSTORE(0, 0)
|
||||
// MLOAD_FROM_SIZE(32, 32)
|
||||
// SSTORE(1, 0)
|
||||
// Memory dump:
|
||||
// 0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 20: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 40: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 60: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 80: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 100: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 120: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 140: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 160: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 180: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 1a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 1c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 1e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 200: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 220: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 240: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 260: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 280: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 2a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 2c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 2e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 300: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 320: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 340: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 360: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 380: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 3a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 3c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 3e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 400: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 420: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 440: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 460: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 480: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 4a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 4c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 4e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 500: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 520: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 540: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 560: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 580: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 5a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 5c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 5e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 600: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 620: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 640: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 660: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 680: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 6a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 6c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 6e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 700: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 720: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 740: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 760: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 780: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 7a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 7c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 7e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 800: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 820: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 840: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 860: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 880: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 8a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 8c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 8e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 900: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 920: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 940: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 960: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 980: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 9a0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 9c0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 9e0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a00: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a20: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a40: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a60: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// a80: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// aa0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// ac0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// ae0: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// b00: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// b20: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// b40: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// b60: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000000
|
16
test/libyul/yulInterpreterTests/dataoffset.yul
Normal file
16
test/libyul/yulInterpreterTests/dataoffset.yul
Normal file
@ -0,0 +1,16 @@
|
||||
object "main"
|
||||
{
|
||||
code {
|
||||
sstore(0, dataoffset("main"))
|
||||
sstore(1, dataoffset("sub"))
|
||||
}
|
||||
object "sub" { code { sstore(0, 1) } }
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// SSTORE(0, 110)
|
||||
// SSTORE(1, 1804)
|
||||
// Memory dump:
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 000000000000000000000000000000000000000000000000000000000000006e
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 000000000000000000000000000000000000000000000000000000000000070c
|
16
test/libyul/yulInterpreterTests/datasize.yul
Normal file
16
test/libyul/yulInterpreterTests/datasize.yul
Normal file
@ -0,0 +1,16 @@
|
||||
object "main"
|
||||
{
|
||||
code {
|
||||
sstore(0, datasize("main"))
|
||||
sstore(1, datasize("sub"))
|
||||
}
|
||||
object "sub" { code { sstore(0, 1) } }
|
||||
}
|
||||
// ----
|
||||
// Trace:
|
||||
// SSTORE(0, 2916)
|
||||
// SSTORE(1, 265)
|
||||
// Memory dump:
|
||||
// Storage dump:
|
||||
// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000b64
|
||||
// 0000000000000000000000000000000000000000000000000000000000000001: 0000000000000000000000000000000000000000000000000000000000000109
|
@ -80,7 +80,8 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
{
|
||||
yulFuzzerUtil::interpret(
|
||||
os1,
|
||||
stack.parserResult()->code
|
||||
stack.parserResult()->code,
|
||||
*EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
|
||||
);
|
||||
}
|
||||
catch (yul::test::StepLimitReached const&)
|
||||
@ -97,6 +98,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
yulFuzzerUtil::interpret(
|
||||
os2,
|
||||
stack.parserResult()->code,
|
||||
*EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
|
||||
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
|
||||
);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ using namespace yul::test::yul_fuzzer;
|
||||
void yulFuzzerUtil::interpret(
|
||||
ostream& _os,
|
||||
shared_ptr<yul::Block> _ast,
|
||||
Dialect const& _dialect,
|
||||
size_t _maxSteps,
|
||||
size_t _maxTraceSize,
|
||||
size_t _maxMemory
|
||||
@ -32,7 +33,7 @@ void yulFuzzerUtil::interpret(
|
||||
state.maxTraceSize = _maxTraceSize;
|
||||
state.maxSteps = _maxSteps;
|
||||
state.maxMemSize = _maxMemory;
|
||||
Interpreter interpreter(state);
|
||||
Interpreter interpreter(state, _dialect);
|
||||
interpreter(*_ast);
|
||||
_os << "Trace:" << endl;
|
||||
for (auto const& line: interpreter.trace())
|
||||
|
@ -15,6 +15,7 @@
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <test/tools/yulInterpreter/Interpreter.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
namespace yul
|
||||
{
|
||||
@ -27,6 +28,7 @@ struct yulFuzzerUtil
|
||||
static void interpret(
|
||||
std::ostream& _os,
|
||||
std::shared_ptr<yul::Block> _ast,
|
||||
Dialect const& _dialect,
|
||||
size_t _maxSteps = maxSteps,
|
||||
size_t _maxTraceSize = maxTraceSize,
|
||||
size_t _maxMemory = maxMemory
|
||||
|
@ -23,8 +23,9 @@
|
||||
#include <src/libfuzzer/libfuzzer_macro.h>
|
||||
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <test/tools/ossfuzz/yulFuzzerCommon.h>
|
||||
|
||||
@ -76,7 +77,8 @@ DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
{
|
||||
yulFuzzerUtil::interpret(
|
||||
os1,
|
||||
stack.parserResult()->code
|
||||
stack.parserResult()->code,
|
||||
*EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion())
|
||||
);
|
||||
}
|
||||
catch (yul::test::StepLimitReached const&)
|
||||
@ -90,8 +92,10 @@ DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
stack.optimize();
|
||||
try
|
||||
{
|
||||
yulFuzzerUtil::interpret(os2,
|
||||
yulFuzzerUtil::interpret(
|
||||
os2,
|
||||
stack.parserResult()->code,
|
||||
*EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()),
|
||||
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 1.5)
|
||||
);
|
||||
}
|
||||
|
@ -444,6 +444,29 @@ u256 EVMInstructionInterpreter::eval(
|
||||
return 0;
|
||||
}
|
||||
|
||||
u256 EVMInstructionInterpreter::evalBuiltin(YulString _name, const std::vector<u256>& _arguments)
|
||||
{
|
||||
if (_name == "datasize"_yulstring)
|
||||
return u256(keccak256(h256(_arguments.at(0)))) & 0xfff;
|
||||
else if (_name == "dataoffset"_yulstring)
|
||||
return u256(keccak256(h256(_arguments.at(0) + 2))) & 0xfff;
|
||||
else if (_name == "datacopy"_yulstring)
|
||||
{
|
||||
// This is identical to codecopy.
|
||||
if (logMemoryWrite(_arguments.at(0), _arguments.at(2)))
|
||||
copyZeroExtended(
|
||||
m_state.memory,
|
||||
m_state.code,
|
||||
size_t(_arguments.at(0)),
|
||||
size_t(_arguments.at(1) & size_t(-1)),
|
||||
size_t(_arguments.at(2))
|
||||
);
|
||||
}
|
||||
else
|
||||
yulAssert(false, "Unknown builtin: " + _name.str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EVMInstructionInterpreter::logMemoryRead(u256 const& _offset, u256 const& _size)
|
||||
{
|
||||
return logMemory(false, _offset, _size);
|
||||
|
@ -36,6 +36,7 @@ enum class Instruction: uint8_t;
|
||||
|
||||
namespace yul
|
||||
{
|
||||
class YulString;
|
||||
namespace test
|
||||
{
|
||||
|
||||
@ -66,7 +67,10 @@ public:
|
||||
explicit EVMInstructionInterpreter(InterpreterState& _state):
|
||||
m_state(_state)
|
||||
{}
|
||||
/// Evaluate instruction
|
||||
dev::u256 eval(dev::eth::Instruction _instruction, std::vector<dev::u256> const& _arguments);
|
||||
/// Evaluate builtin function
|
||||
dev::u256 evalBuiltin(YulString _name, std::vector<dev::u256> const& _arguments);
|
||||
|
||||
private:
|
||||
/// Record a memory read in the trace. Also updates m_state.msize
|
||||
|
@ -23,7 +23,9 @@
|
||||
#include <test/tools/yulInterpreter/EVMInstructionInterpreter.h>
|
||||
|
||||
#include <libyul/AsmData.h>
|
||||
#include <libyul/Dialect.h>
|
||||
#include <libyul/Utilities.h>
|
||||
#include <libyul/backends/evm/EVMDialect.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
@ -157,14 +159,14 @@ void Interpreter::operator()(Block const& _block)
|
||||
|
||||
u256 Interpreter::evaluate(Expression const& _expression)
|
||||
{
|
||||
ExpressionEvaluator ev(m_state, m_variables, m_functions);
|
||||
ExpressionEvaluator ev(m_state, m_dialect, m_variables, m_functions);
|
||||
ev.visit(_expression);
|
||||
return ev.value();
|
||||
}
|
||||
|
||||
vector<u256> Interpreter::evaluateMulti(Expression const& _expression)
|
||||
{
|
||||
ExpressionEvaluator ev(m_state, m_variables, m_functions);
|
||||
ExpressionEvaluator ev(m_state, m_dialect, m_variables, m_functions);
|
||||
ev.visit(_expression);
|
||||
return ev.values();
|
||||
}
|
||||
@ -204,9 +206,16 @@ void ExpressionEvaluator::operator()(FunctionalInstruction const& _instr)
|
||||
|
||||
void ExpressionEvaluator::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
solAssert(m_functions.count(_funCall.functionName.name), "");
|
||||
evaluateArgs(_funCall.arguments);
|
||||
|
||||
if (dynamic_cast<EVMDialect const*>(&m_dialect) && m_dialect.builtin(_funCall.functionName.name))
|
||||
{
|
||||
EVMInstructionInterpreter interpreter(m_state);
|
||||
setValue(interpreter.evalBuiltin(_funCall.functionName.name, values()));
|
||||
return;
|
||||
}
|
||||
|
||||
solAssert(m_functions.count(_funCall.functionName.name), "");
|
||||
FunctionDefinition const& fun = *m_functions.at(_funCall.functionName.name);
|
||||
solAssert(m_values.size() == fun.parameters.size(), "");
|
||||
map<YulString, u256> variables;
|
||||
@ -217,7 +226,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall)
|
||||
|
||||
// TODO function name lookup could be a little more efficient,
|
||||
// we have to copy the list here.
|
||||
Interpreter interpreter(m_state, variables, m_functions);
|
||||
Interpreter interpreter(m_state, m_dialect, variables, m_functions);
|
||||
interpreter(fun.body);
|
||||
|
||||
m_values.clear();
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
namespace yul
|
||||
{
|
||||
struct Dialect;
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
@ -100,9 +102,11 @@ class Interpreter: public ASTWalker
|
||||
public:
|
||||
Interpreter(
|
||||
InterpreterState& _state,
|
||||
Dialect const& _dialect,
|
||||
std::map<YulString, dev::u256> _variables = {},
|
||||
std::map<YulString, FunctionDefinition const*> _functions = {}
|
||||
):
|
||||
m_dialect(_dialect),
|
||||
m_state(_state),
|
||||
m_variables(std::move(_variables)),
|
||||
m_functions(std::move(_functions))
|
||||
@ -133,6 +137,7 @@ private:
|
||||
/// Unregisters variables.
|
||||
void closeScope();
|
||||
|
||||
Dialect const& m_dialect;
|
||||
InterpreterState& m_state;
|
||||
/// Values of variables.
|
||||
std::map<YulString, dev::u256> m_variables;
|
||||
@ -150,10 +155,12 @@ class ExpressionEvaluator: public ASTWalker
|
||||
public:
|
||||
ExpressionEvaluator(
|
||||
InterpreterState& _state,
|
||||
Dialect const& _dialect,
|
||||
std::map<YulString, dev::u256> const& _variables,
|
||||
std::map<YulString, FunctionDefinition const*> const& _functions
|
||||
):
|
||||
m_state(_state),
|
||||
m_dialect(_dialect),
|
||||
m_variables(_variables),
|
||||
m_functions(_functions)
|
||||
{}
|
||||
@ -176,6 +183,7 @@ private:
|
||||
void evaluateArgs(std::vector<Expression> const& _expr);
|
||||
|
||||
InterpreterState& m_state;
|
||||
Dialect const& m_dialect;
|
||||
/// Values of variables.
|
||||
std::map<YulString, dev::u256> const& m_variables;
|
||||
/// Meanings of functions.
|
||||
|
@ -88,7 +88,8 @@ void interpret(string const& _source)
|
||||
InterpreterState state;
|
||||
state.maxTraceSize = 10000;
|
||||
state.maxMemSize = 0x20000000;
|
||||
Interpreter interpreter(state);
|
||||
shared_ptr<Dialect> dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}));
|
||||
Interpreter interpreter(state, *dialect);
|
||||
try
|
||||
{
|
||||
interpreter(*ast);
|
||||
|
Loading…
Reference in New Issue
Block a user