Merge remote-tracking branch 'origin/develop' into develop_060

This commit is contained in:
chriseth
2019-11-27 19:14:08 +01:00
33 changed files with 298 additions and 158 deletions
+19 -21
View File
@@ -33,24 +33,21 @@
using namespace std;
using namespace dev;
using namespace dev::test;
using namespace evmc::literals;
evmc::VM* EVMHost::getVM(string const& _path)
evmc::VM& EVMHost::getVM(string const& _path)
{
static unique_ptr<evmc::VM> theVM;
static evmc::VM theVM;
if (!theVM && !_path.empty())
{
evmc_loader_error_code errorCode = {};
evmc_vm* vm = evmc_load_and_configure(_path.c_str(), &errorCode);
auto vm = evmc::VM{evmc_load_and_configure(_path.c_str(), &errorCode)};
if (vm && errorCode == EVMC_LOADER_SUCCESS)
{
if (evmc_vm_has_capability(vm, EVMC_CAPABILITY_EVM1))
theVM = make_unique<evmc::VM>(vm);
if (vm.get_capabilities() & EVMC_CAPABILITY_EVM1)
theVM = std::move(vm);
else
{
evmc_destroy(vm);
cerr << "VM loaded does not support EVM1" << endl;
}
}
else
{
@@ -60,10 +57,10 @@ evmc::VM* EVMHost::getVM(string const& _path)
cerr << endl;
}
}
return theVM.get();
return theVM;
}
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm):
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
m_vm(_vm),
m_evmVersion(_evmVersion)
{
@@ -118,21 +115,21 @@ void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _ben
evmc::result EVMHost::call(evmc_message const& _message) noexcept
{
if (_message.destination == convertToEVMC(Address(1)))
if (_message.destination == 0x0000000000000000000000000000000000000001_address)
return precompileECRecover(_message);
else if (_message.destination == convertToEVMC(Address(2)))
else if (_message.destination == 0x0000000000000000000000000000000000000002_address)
return precompileSha256(_message);
else if (_message.destination == convertToEVMC(Address(3)))
else if (_message.destination == 0x0000000000000000000000000000000000000003_address)
return precompileRipeMD160(_message);
else if (_message.destination == convertToEVMC(Address(4)))
else if (_message.destination == 0x0000000000000000000000000000000000000004_address)
return precompileIdentity(_message);
else if (_message.destination == convertToEVMC(Address(5)))
else if (_message.destination == 0x0000000000000000000000000000000000000005_address)
return precompileModExp(_message);
else if (_message.destination == convertToEVMC(Address(6)))
else if (_message.destination == 0x0000000000000000000000000000000000000006_address)
return precompileALTBN128G1Add(_message);
else if (_message.destination == convertToEVMC(Address(7)))
else if (_message.destination == 0x0000000000000000000000000000000000000007_address)
return precompileALTBN128G1Mul(_message);
else if (_message.destination == convertToEVMC(Address(8)))
else if (_message.destination == 0x0000000000000000000000000000000000000008_address)
return precompileALTBN128PairingProduct(_message);
State stateBackup = m_state;
@@ -192,7 +189,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
evmc::address currentAddress = m_currentAddress;
m_currentAddress = message.destination;
evmc::result result = m_vm->execute(*this, m_evmRevision, message, code.data(), code.size());
evmc::result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size());
m_currentAddress = currentAddress;
if (message.kind == EVMC_CREATE)
@@ -224,10 +221,11 @@ evmc_tx_context EVMHost::get_tx_context() noexcept
ctx.block_timestamp = m_state.timestamp;
ctx.block_number = m_state.blockNumber;
ctx.block_coinbase = m_coinbase;
// TODO: support short literals in EVMC and use them here
ctx.block_difficulty = convertToEVMC(u256("200000000"));
ctx.block_gas_limit = 20000000;
ctx.tx_gas_price = convertToEVMC(u256("3000000000"));
ctx.tx_origin = convertToEVMC(Address("0x9292929292929292929292929292929292929292"));
ctx.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155
ctx.chain_id = convertToEVMC(u256(1));
return ctx;
+3 -3
View File
@@ -40,9 +40,9 @@ public:
/// Tries to dynamically load libevmone. @returns nullptr on failure.
/// The path has to be provided for the first successful run and will be ignored
/// afterwards.
static evmc::VM* getVM(std::string const& _path = {});
static evmc::VM& getVM(std::string const& _path = {});
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM* _vm = getVM());
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm = getVM());
struct Account
{
@@ -179,7 +179,7 @@ private:
/// @note The return value is only valid as long as @a _data is alive!
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
evmc::VM* m_vm = nullptr;
evmc::VM& m_vm;
// EVM version requested by the testing tool
langutil::EVMVersion m_evmVersion;
// EVM version requested from EVMC (matches the above)
+1 -1
View File
@@ -96,7 +96,7 @@ int registerTests(
{
static vector<unique_ptr<string>> filenames;
filenames.emplace_back(new string(_path.string()));
filenames.emplace_back(make_unique<string>(_path.string()));
_suite.add(make_test_case(
[config, _testCaseCreator]
{
+1 -1
View File
@@ -223,7 +223,7 @@ protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "GlobalRegistrar")));
s_compiledRegistrar = make_unique<bytes>(compileContract(registrarCode, "GlobalRegistrar"));
sendMessage(*s_compiledRegistrar, true);
BOOST_REQUIRE(m_transactionSuccessful);
+1 -1
View File
@@ -132,7 +132,7 @@ protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
s_compiledRegistrar.reset(new bytes(compileContract(registrarCode, "FixedFeeRegistrar")));
s_compiledRegistrar = make_unique<bytes>(compileContract(registrarCode, "FixedFeeRegistrar"));
sendMessage(*s_compiledRegistrar, true);
BOOST_REQUIRE(m_transactionSuccessful);
+1 -1
View File
@@ -451,7 +451,7 @@ protected:
)
{
if (!s_compiledWallet)
s_compiledWallet.reset(new bytes(compileContract(walletCode, "Wallet")));
s_compiledWallet = make_unique<bytes>(compileContract(walletCode, "Wallet"));
bytes args = encodeArgs(u256(0x60), _required, _dailyLimit, u256(_owners.size()), _owners);
sendMessage(*s_compiledWallet + args, true, _value);
+59 -3
View File
@@ -18,7 +18,7 @@
* Unit tests for the StringUtils routines.
*/
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/FixedHash.h>
#include <libsolidity/ast/Types.h> // for IntegerType
@@ -28,6 +28,9 @@
using namespace std;
using namespace dev::solidity;
// TODO: Fix Boost...
BOOST_TEST_DONT_PRINT_LOG_VALUE(dev::bytes);
namespace dev
{
namespace test
@@ -35,9 +38,62 @@ namespace test
BOOST_AUTO_TEST_SUITE(CommonData)
BOOST_AUTO_TEST_CASE(test_to_hex)
BOOST_AUTO_TEST_CASE(fromhex_char)
{
BOOST_CHECK_EQUAL(toHex(fromHex("FF"), HexPrefix::DontAdd, HexCase::Lower), "ff");
BOOST_CHECK_EQUAL(fromHex('0', WhenError::DontThrow), 0x0);
BOOST_CHECK_EQUAL(fromHex('a', WhenError::DontThrow), 0xa);
BOOST_CHECK_EQUAL(fromHex('x', WhenError::DontThrow), -1);
BOOST_CHECK_EQUAL(fromHex('x', static_cast<WhenError>(42)), -1);
BOOST_CHECK_EQUAL(fromHex('0', WhenError::Throw), 0x0);
BOOST_CHECK_EQUAL(fromHex('a', WhenError::Throw), 0xa);
BOOST_CHECK_THROW(fromHex('x', WhenError::Throw), BadHexCharacter);
}
BOOST_AUTO_TEST_CASE(fromhex_string)
{
bytes expectation_even = {{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}};
bytes expectation_odd = {{0x00, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0}};
// Defaults to WhenError::DontThrow
BOOST_CHECK_EQUAL(fromHex(""), bytes());
BOOST_CHECK_EQUAL(fromHex("00112233445566778899aabbccddeeff"), expectation_even);
BOOST_CHECK_EQUAL(fromHex("0x00112233445566778899aabbccddeeff"), expectation_even);
BOOST_CHECK_EQUAL(fromHex("0x00112233445566778899aabbccddeeff0"), expectation_odd);
BOOST_CHECK_EQUAL(fromHex("gg"), bytes());
BOOST_CHECK_EQUAL(fromHex("0xgg"), bytes());
BOOST_CHECK_EQUAL(fromHex("", WhenError::Throw), bytes());
BOOST_CHECK_EQUAL(fromHex("00112233445566778899aabbccddeeff", WhenError::Throw), expectation_even);
BOOST_CHECK_EQUAL(fromHex("0x00112233445566778899aabbccddeeff", WhenError::Throw), expectation_even);
BOOST_CHECK_EQUAL(fromHex("0x00112233445566778899aabbccddeeff0", WhenError::Throw), expectation_odd);
BOOST_CHECK_THROW(fromHex("gg", WhenError::Throw), BadHexCharacter);
BOOST_CHECK_THROW(fromHex("0xgg", WhenError::Throw), BadHexCharacter);
}
BOOST_AUTO_TEST_CASE(tohex_uint8)
{
BOOST_CHECK_EQUAL(toHex(0xaa), "aa");
BOOST_CHECK_EQUAL(toHex(0xaa, HexCase::Lower), "aa");
BOOST_CHECK_EQUAL(toHex(0xaa, HexCase::Upper), "AA");
BOOST_CHECK_THROW(toHex(0xaa, HexCase::Mixed), BadHexCase);
// Defaults to lower case on invalid setting.
BOOST_CHECK_EQUAL(toHex(0xaa, static_cast<HexCase>(42)), "aa");
}
BOOST_AUTO_TEST_CASE(tohex_bytes)
{
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::DontAdd, HexCase::Lower), "00112233445566778899aabbccddeeff");
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::DontAdd, HexCase::Upper), "00112233445566778899AABBCCDDEEFF");
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::DontAdd, HexCase::Mixed), "00112233445566778899aabbCCDDeeff");
// Defaults to lower case on invalid setting.
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::DontAdd, static_cast<HexCase>(42)), "00112233445566778899aabbccddeeff");
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::Add, HexCase::Lower), "0x00112233445566778899aabbccddeeff");
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::Add, HexCase::Upper), "0x00112233445566778899AABBCCDDEEFF");
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899AaBbCcDdEeFf"), HexPrefix::Add, HexCase::Mixed), "0x00112233445566778899aabbCCDDeeff");
// Defaults to lower case on invalid setting.
BOOST_CHECK_EQUAL(toHex(fromHex("00112233445566778899aAbBcCdDeEfF"), HexPrefix::Add, static_cast<HexCase>(42)), "0x00112233445566778899aabbccddeeff");
}
BOOST_AUTO_TEST_CASE(test_format_number)
+1 -1
View File
@@ -36,7 +36,7 @@ class ABIJsonTest: public TestCase
{
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{ return std::unique_ptr<TestCase>(new ABIJsonTest(_config.filename)); }
{ return std::make_unique<ABIJsonTest>(_config.filename); }
ABIJsonTest(std::string const& _filename);
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override;
+1 -1
View File
@@ -36,7 +36,7 @@ class ASTJSONTest: public TestCase
{
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{ return std::unique_ptr<TestCase>(new ASTJSONTest(_config.filename)); }
{ return std::make_unique<ASTJSONTest>(_config.filename); }
ASTJSONTest(std::string const& _filename);
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override;
+1 -1
View File
@@ -37,7 +37,7 @@ class EWasmTranslationTest: public dev::solidity::test::EVMVersionRestrictedTest
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{
return std::unique_ptr<TestCase>(new EWasmTranslationTest(_config.filename));
return std::make_unique<EWasmTranslationTest>(_config.filename);
}
explicit EWasmTranslationTest(std::string const& _filename);
+1 -1
View File
@@ -34,7 +34,7 @@ class FunctionSideEffects: public dev::solidity::test::TestCase
{
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{ return std::unique_ptr<TestCase>(new FunctionSideEffects(_config.filename)); }
{ return std::make_unique<FunctionSideEffects>(_config.filename); }
explicit FunctionSideEffects(std::string const& _filename);
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override;
+1 -1
View File
@@ -42,7 +42,7 @@ class ObjectCompilerTest: public dev::solidity::test::TestCase
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{
return std::unique_ptr<TestCase>(new ObjectCompilerTest(_config.filename));
return std::make_unique<ObjectCompilerTest>(_config.filename);
}
explicit ObjectCompilerTest(std::string const& _filename);
+1 -1
View File
@@ -42,7 +42,7 @@ class YulInterpreterTest: public dev::solidity::test::EVMVersionRestrictedTestCa
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{
return std::unique_ptr<TestCase>(new YulInterpreterTest(_config.filename));
return std::make_unique<YulInterpreterTest>(_config.filename);
}
explicit YulInterpreterTest(std::string const& _filename);
+5 -1
View File
@@ -424,7 +424,11 @@ void YulOptimizerTest::disambiguate()
void YulOptimizerTest::updateContext()
{
m_nameDispenser = make_unique<NameDispenser>(*m_dialect, *m_ast, m_reservedIdentifiers);
m_context = unique_ptr<OptimiserStepContext>(new OptimiserStepContext{*m_dialect, *m_nameDispenser, m_reservedIdentifiers});
m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{
*m_dialect,
*m_nameDispenser,
m_reservedIdentifiers
});
}
void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors)
+1 -1
View File
@@ -51,7 +51,7 @@ class YulOptimizerTest: public dev::solidity::test::EVMVersionRestrictedTestCase
public:
static std::unique_ptr<TestCase> create(Config const& _config)
{
return std::unique_ptr<TestCase>(new YulOptimizerTest(_config.filename));
return std::make_unique<YulOptimizerTest>(_config.filename);
}
explicit YulOptimizerTest(std::string const& _filename);
@@ -0,0 +1,20 @@
{
let x := 0
switch mload(x)
case 0 { x := x }
case 1 { x := 1 }
default { invalid() }
mstore(1, 1)
}
// ====
// step: fullSuite
// ----
// {
// {
// switch mload(0)
// case 0 { }
// case 1 { }
// default { invalid() }
// mstore(1, 1)
// }
// }
+1 -1
View File
@@ -142,7 +142,7 @@ DEFINE_PROTO_FUZZER(Contract const& _input)
// We target the default EVM which is the latest
langutil::EVMVersion version = {};
EVMHost hostContext(version, &evmone);
EVMHost hostContext(version, evmone);
// Deploy contract and signal failure if deploy failed
evmc::result createResult = deployContract(hostContext, byteCode);
+86 -41
View File
@@ -90,12 +90,35 @@ string ProtoConverter::visit(Literal const& _x)
}
}
void ProtoConverter::consolidateVarDeclsInFunctionDef()
{
m_currentFuncVars.clear();
auto const& scopes = m_funcVars.back();
for (auto const& s: scopes)
for (auto const& var: s)
m_currentFuncVars.push_back(&var);
}
void ProtoConverter::consolidateGlobalVarDecls()
{
m_currentGlobalVars.clear();
for (auto const& scope: m_globalVars)
for (auto const& var: scope)
m_currentGlobalVars.push_back(&var);
}
bool ProtoConverter::varDeclAvailable()
{
if (m_inFunctionDef)
return m_scopeVars.top().size() > 0;
{
consolidateVarDeclsInFunctionDef();
return m_currentFuncVars.size() > 0;
}
else
return m_variables.size() > 0;
{
consolidateGlobalVarDecls();
return m_currentGlobalVars.size() > 0;
}
}
bool ProtoConverter::functionCallNotPossible(FunctionCall_Returns _type)
@@ -109,14 +132,14 @@ void ProtoConverter::visit(VarRef const& _x)
if (m_inFunctionDef)
{
// Ensure that there is at least one variable declaration to reference in function scope.
yulAssert(m_scopeVars.top().size() > 0, "Proto fuzzer: No variables to reference.");
m_output << m_scopeVars.top()[_x.varnum() % m_scopeVars.top().size()];
yulAssert(m_currentFuncVars.size() > 0, "Proto fuzzer: No variables to reference.");
m_output << *m_currentFuncVars[_x.varnum() % m_currentFuncVars.size()];
}
else
{
// Ensure that there is at least one variable declaration to reference in nested scopes.
yulAssert(m_variables.size() > 0, "Proto fuzzer: No variables to reference.");
m_output << m_variables[_x.varnum() % m_variables.size()];
yulAssert(m_currentGlobalVars.size() > 0, "Proto fuzzer: No global variables to reference.");
m_output << *m_currentGlobalVars[_x.varnum() % m_currentGlobalVars.size()];
}
}
@@ -258,8 +281,10 @@ void ProtoConverter::visit(VarDecl const& _x)
m_output << "let " << varName << " := ";
visit(_x.expr());
m_output << "\n";
m_scopeVars.top().push_back(varName);
m_variables.push_back(varName);
if (m_inFunctionDef)
m_funcVars.back().back().push_back(varName);
else
m_globalVars.back().push_back(varName);
}
void ProtoConverter::visit(TypedVarDecl const& _x)
@@ -324,8 +349,10 @@ void ProtoConverter::visit(TypedVarDecl const& _x)
m_output << " : u256\n";
break;
}
m_scopeVars.top().push_back(varName);
m_variables.push_back(varName);
if (m_inFunctionDef)
m_funcVars.back().back().push_back(varName);
else
m_globalVars.back().push_back(varName);
}
void ProtoConverter::visit(UnaryOp const& _x)
@@ -1106,12 +1133,19 @@ void ProtoConverter::visit(Statement const& _x)
}
}
void ProtoConverter::openScope(vector<string> const& _funcParams)
void ProtoConverter::openBlockScope()
{
m_scopeVars.push({});
m_scopeFuncs.push({});
if (!_funcParams.empty())
addVarsToScope(_funcParams);
m_scopeFuncs.push_back({});
// Create new block scope inside current function scope
if (m_inFunctionDef)
m_funcVars.back().push_back(vector<string>{});
else
m_globalVars.push_back(vector<string>{});
}
void ProtoConverter::openFunctionScope(vector<string> const& _funcParams)
{
m_funcVars.push_back(vector<vector<string>>({_funcParams}));
}
void ProtoConverter::updateFunctionMaps(string const& _var)
@@ -1128,21 +1162,9 @@ void ProtoConverter::updateFunctionMaps(string const& _var)
yulAssert(erased == 2, "Proto fuzzer: Function maps not updated");
}
void ProtoConverter::closeScope()
void ProtoConverter::closeBlockScope()
{
for (auto const& var: m_scopeVars.top())
{
unsigned numVarsRemoved = m_variables.size();
m_variables.erase(remove(m_variables.begin(), m_variables.end(), var), m_variables.end());
numVarsRemoved -= m_variables.size();
yulAssert(
numVarsRemoved == 1,
"Proto fuzzer: Nothing or too much went out of scope"
);
}
m_scopeVars.pop();
for (auto const& f: m_scopeFuncs.top())
for (auto const& f: m_scopeFuncs.back())
{
unsigned numFuncsRemoved = m_functions.size();
m_functions.erase(remove(m_functions.begin(), m_functions.end(), f), m_functions.end());
@@ -1153,21 +1175,40 @@ void ProtoConverter::closeScope()
);
updateFunctionMaps(f);
}
m_scopeFuncs.pop();
if (!m_scopeFuncs.empty())
m_scopeFuncs.pop_back();
if (!m_inFunctionDef)
{
if (!m_globalVars.empty())
m_globalVars.pop_back();
}
else
{
// Variables that have been declared in a
// function block, go out of scope
if (!m_funcVars.empty())
if (!m_funcVars.back().empty())
m_funcVars.back().pop_back();
}
}
void ProtoConverter::closeFunctionScope()
{
if (!m_funcVars.empty())
m_funcVars.pop_back();
}
void ProtoConverter::addVarsToScope(vector<string> const& _vars)
{
for (string const& i: _vars)
{
m_variables.push_back(i);
m_scopeVars.top().push_back(i);
}
if (m_inFunctionDef)
m_funcVars.back().back().insert(m_funcVars.back().back().end(), _vars.begin(), _vars.end());
else
m_globalVars.back().insert(m_globalVars.back().end(), _vars.begin(), _vars.end());
}
void ProtoConverter::visit(Block const& _x, vector<string> _funcParams)
void ProtoConverter::visit(Block const& _x)
{
openScope(_funcParams);
openBlockScope();
// Register function declarations in this scope unless this
// scope belongs to for-init (in which function declarations
@@ -1185,7 +1226,7 @@ void ProtoConverter::visit(Block const& _x, vector<string> _funcParams)
}
else
m_output << "{}\n";
closeScope();
closeBlockScope();
}
vector<string> ProtoConverter::createVars(unsigned _startIdx, unsigned _endIdx)
@@ -1228,7 +1269,7 @@ void ProtoConverter::registerFunction(FunctionDef const* _x)
auto ret = m_functionSigMap.emplace(make_pair(funcName, make_pair(numInParams, numOutParams)));
yulAssert(ret.second, "Proto fuzzer: Function already exists.");
m_functions.push_back(funcName);
m_scopeFuncs.top().push_back(funcName);
m_scopeFuncs.back().push_back(funcName);
m_functionDefMap.emplace(make_pair(_x, funcName));
}
@@ -1367,8 +1408,12 @@ void ProtoConverter::createFunctionDefAndCall(
bool wasInFunctionDef = m_inFunctionDef;
m_inFunctionDef = true;
// Body
visit(_x.block(), varsVec);
// Create new function scope and add function input and return
// parameters to it.
openFunctionScope(varsVec);
// Visit function body
visit(_x.block());
closeFunctionScope();
m_inForBodyScope = wasInForBody;
m_inFunctionDef = wasInFunctionDef;
+27 -9
View File
@@ -42,6 +42,8 @@ class ProtoConverter
public:
ProtoConverter()
{
m_funcVars = std::vector<std::vector<std::vector<std::string>>>{};
m_globalVars = std::vector<std::vector<std::string>>{};
m_inForBodyScope = false;
m_inForInitScope = false;
m_numNestedForLoops = 0;
@@ -62,7 +64,7 @@ private:
/// @param _block Reference to a basic block of yul statements.
/// @param _funcParams List of function parameter names, defaults to
/// an empty vector.
void visit(Block const& _block, std::vector<std::string> _funcParams = {});
void visit(Block const& _block);
std::string visit(Literal const&);
void visit(VarRef const&);
@@ -99,11 +101,15 @@ private:
void visit(Code const&);
void visit(Program const&);
/// Creates a new scope, and adds @a _funcParams to it if it
/// Creates a new block scope.
void openBlockScope();
/// Creates a new function scope, and adds @a _funcParams to it if it
/// is non-empty.
void openScope(std::vector<std::string> const& _funcParams);
/// Closes current scope
void closeScope();
void openFunctionScope(std::vector<std::string> const& _funcParams);
/// Closes current block scope
void closeBlockScope();
/// Closes current function scope
void closeFunctionScope();
/// Adds @a _vars to current scope
void addVarsToScope(std::vector<std::string> const& _vars);
@@ -139,6 +145,14 @@ private:
/// Multiple -> "m"
std::string functionTypeToString(NumFunctionReturns _type);
/// Builds a single vector containing variables declared in
/// function scope.
void consolidateVarDeclsInFunctionDef();
/// Builds a single vector containing variables declared in
/// global scope.
void consolidateGlobalVarDecls();
/// Return true if at least one variable declaration is in scope,
/// false otherwise.
/// @return True in the following cases:
@@ -296,12 +310,16 @@ private:
}
std::ostringstream m_output;
/// Variables in current scope
std::stack<std::vector<std::string>> m_scopeVars;
/// Variables in all function definitions
std::vector<std::vector<std::vector<std::string>>> m_funcVars;
/// Variables in current function definition
std::vector<std::string const*> m_currentFuncVars;
/// Variables in global scope
std::vector<std::string const*> m_currentGlobalVars;
/// Functions in current scope
std::stack<std::vector<std::string>> m_scopeFuncs;
std::vector<std::vector<std::string>> m_scopeFuncs;
/// Variables
std::vector<std::string> m_variables;
std::vector<std::vector<std::string>> m_globalVars;
/// Functions
std::vector<std::string> m_functions;
/// Maps FunctionDef object to its name
+9 -17
View File
@@ -55,8 +55,7 @@ void printErrors(ostream& _stream, ErrorList const& _errors)
DEFINE_PROTO_FUZZER(Program const& _input)
{
ProtoConverter converter;
string yul_source = converter.programToString(_input);
string yul_source = ProtoConverter().programToString(_input);
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
{
@@ -70,24 +69,17 @@ DEFINE_PROTO_FUZZER(Program const& _input)
// AssemblyStack entry point
AssemblyStack stack(
langutil::EVMVersion(langutil::EVMVersion::istanbul()),
langutil::EVMVersion::istanbul(),
AssemblyStack::Language::StrictAssembly,
dev::solidity::OptimiserSettings::full()
);
try
// Parse protobuf mutated YUL code
if (!stack.parseAndAnalyze("source", yul_source) || !stack.parserResult()->code ||
!stack.parserResult()->analysisInfo)
{
// Parse protobuf mutated YUL code
if (!stack.parseAndAnalyze("source", yul_source) || !stack.parserResult()->code ||
!stack.parserResult()->analysisInfo)
{
printErrors(std::cout, stack.errors());
return;
}
}
catch (Exception const&)
{
return;
printErrors(std::cout, stack.errors());
yulAssert(false, "Proto fuzzer generated malformed program");
}
ostringstream os1;
@@ -95,7 +87,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(langutil::EVMVersion::istanbul()))
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion::istanbul())
);
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
@@ -105,7 +97,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
termReason = yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion(langutil::EVMVersion::istanbul())),
EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion::istanbul()),
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 4)
);