Reset between runs, redeploying library.

This commit is contained in:
Bhargava Shastry 2021-04-07 16:25:49 +02:00
parent 7b1ade9223
commit af94138b53
4 changed files with 60 additions and 49 deletions

View File

@ -33,6 +33,8 @@ using namespace std;
optional<CompilerOutput> SolidityCompilationFramework::compileContract()
{
// Reset since compiler stack may be called multiple times.
m_compiler.reset(true);
m_compiler.setSources(m_compilerInput.sourceCode);
m_compiler.setLibraries(m_compilerInput.libraryAddresses);
m_compiler.setEVMVersion(m_compilerInput.evmVersion);
@ -84,7 +86,7 @@ optional<Json::Value> SolidityCompilationFramework::randomFunction(size_t _seed)
else
{
uniform_int_distribution<unsigned> d(0, contractABI.size() - 1);
minstd_rand r(_seed);
mt19937_64 r(_seed);
return contractABI[d(r)];
}
}

View File

@ -152,8 +152,30 @@ string fixedBytes(
std::string ValueGenerator::addressLiteral()
{
std::uniform_int_distribution<size_t> dist(0, m_addresses.size() - 1);
return "0x" + m_addresses[dist(m_rand)].hex();
auto iter = m_addressSelector.begin();
std::uniform_int_distribution<size_t> dist(0, m_addressSelector.size() - 1);
std::advance(iter, dist(m_rand));
return "0x" + iter->first.hex();
}
std::string ValueGenerator::functionLiteral()
{
std::string contractAddress;
std::string functionSelector;
for (auto const& item: m_addressSelector)
if (!item.second.empty())
{
contractAddress = "0x" + item.first.hex();
auto selectors = item.second;
std::uniform_int_distribution<size_t> dist(0, selectors.size() - 1);
functionSelector = "0x" + selectors[dist(m_rand)];
return contractAddress + ":" + functionSelector;
}
// If no function found, simply output a (valid address, invalid function) pair.
return addressLiteral() +
":" +
"0x" +
fixedBytes(static_cast<size_t>(FixedBytesWidth::Bytes4), m_rand(), true);
}
void ValueGenerator::initialiseType(TypeInfo& _t)
@ -186,10 +208,7 @@ void ValueGenerator::initialiseType(TypeInfo& _t)
_t.value += addressLiteral();
break;
case Type::Function:
_t.value += addressLiteral() +
":" +
"0x" +
fixedBytes(static_cast<size_t>(FixedBytesWidth::Bytes4), m_rand(), true);
_t.value += functionLiteral();
break;
default:
solAssert(false, "Value Generator: Invalid value type.");

View File

@ -137,35 +137,13 @@ public:
explicit ValueGenerator(
Json::Value const& _type,
unsigned _seed,
std::vector<solidity::util::h160> _addresses
std::map<solidity::util::h160, std::vector<std::string>> _addressSelectors
):
m_rand(_seed),
m_type(_type),
m_bernoulli(0.5),
m_addresses(std::move(_addresses))
m_addressSelector(std::move(_addressSelectors))
{}
void boolean()
{
m_stream << (m_bernoulli(m_rand) ? "true" : "false");
}
void string()
{
m_stream << "hello";
}
void bytes()
{
m_stream << "0x1234";
}
void function();
void fixedbytes()
{
}
void address();
void integer()
{
}
void typeHelper(Json::Value const& _type, TypeInfo& _typeInfo);
TypeInfo type(Json::Value const& _type);
void tuple(Json::Value const& _tuple, TypeInfo& _typeInfo);
@ -181,10 +159,11 @@ public:
TypeInfo& _typeInfo
);
std::string addressLiteral();
std::string contractAddress();
std::string functionLiteral();
private:
std::ostringstream m_stream;
std::mt19937_64 m_rand;
Json::Value const& m_type;
std::bernoulli_distribution m_bernoulli;
std::vector<solidity::util::h160> m_addresses;
std::map<solidity::util::h160, std::vector<std::string>> m_addressSelector;
};

View File

@ -54,7 +54,7 @@ namespace
{
string abiEncoding(
Json::Value const& _functionABI,
vector<h160> _addressLiterals,
map<h160, vector<string>> _addressSelectors,
Json::Value const& _methodIdentifiers
)
{
@ -63,7 +63,7 @@ string abiEncoding(
tie(abiTypeString, abiValueString) = ValueGenerator{
_functionABI["inputs"],
0,
_addressLiterals
_addressSelectors
}.type();
string encodedData;
// A function with inputs must contain type names within
@ -131,13 +131,10 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
cout << "Deployed" << endl;
}
vector<h160> addressLiterals;
map<h160, vector<string>> addressSelector;
for (auto const& account: hostContext.accounts)
addressLiterals.push_back(EVMHost::convertFromEVMC(account.first));
addressSelector[EVMHost::convertFromEVMC(account.first)] = {};
hostContext.reset();
evmoneUtil.reset(true);
evmoneUtil.optSetting(compilerSetting);
auto compilerOutput = evmoneUtil.compileContract();
if (!compilerOutput.has_value())
return 0;
@ -150,10 +147,15 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
if (deployResult.status_code != EVMC_SUCCESS)
return 0;
// Add deployed contract to list of address literals.
addressLiterals.push_back(EVMHost::convertFromEVMC(deployResult.create_address));
// Record function selectors in contract
vector<string> functionSelectors;
for (auto const& item: compilerOutput->methodIdentifiersInContract)
functionSelectors.push_back(item.asString());
string encodedData = abiEncoding(r.value(), addressLiterals,
// Add deployed contract to list of address literals.
addressSelector[EVMHost::convertFromEVMC(deployResult.create_address)] = functionSelectors;
string encodedData = abiEncoding(r.value(), addressSelector,
compilerOutput->methodIdentifiersInContract);
auto callResult = evmoneUtil.executeContract(
solidity::util::fromHex(encodedData),
@ -177,13 +179,21 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
compilerSetting.runYulOptimiser = true;
compilerSetting.optimizeStackAllocation = true;
// Reset call state post old code gen run
hostContext.reset();
// Remove contract compiled via old code gen from list of address
// literals.
addressLiterals.pop_back();
evmoneUtil.reset(true);
addressSelector.clear();
evmoneUtil.optSetting(compilerSetting);
evmoneUtil.viaIR(true);
if (!libraryName.empty())
{
auto l = evmoneUtil.compileAndDeployLibrary();
solAssert(l.has_value(), "Deploying library failed for the second time");
}
for (auto const& account: hostContext.accounts)
addressSelector[EVMHost::convertFromEVMC(account.first)] = {};
auto compilerOutputOpt = evmoneUtil.compileContract();
solAssert(compilerOutputOpt.has_value(), "Contract could not be optimised.");
@ -192,8 +202,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
"Contract compiled via new code gen could not be deployed.");
// Add address literal of contract compiled via Yul IR.
addressLiterals.push_back(EVMHost::convertFromEVMC(deployResultOpt.create_address));
string encodedDataIR = abiEncoding(r.value(), addressLiterals,
addressSelector[EVMHost::convertFromEVMC(deployResultOpt.create_address)] = functionSelectors;
string encodedDataIR = abiEncoding(r.value(), addressSelector,
compilerOutput->methodIdentifiersInContract);
auto callResultOpt = evmoneUtil.executeContract(