Permit low-level library function calls.

This commit is contained in:
Bhargava Shastry 2021-04-08 10:30:06 +02:00
parent af94138b53
commit c248b91bfa
3 changed files with 43 additions and 9 deletions

View File

@ -156,7 +156,7 @@ evmc::result EvmoneUtility::deployAndExecute(
return callResult;
}
optional<evmc::result> EvmoneUtility::compileAndDeployLibrary()
optional<EvmoneUtility::LibraryStatus> EvmoneUtility::compileAndDeployLibrary()
{
solAssert(!m_libraryName.empty(), "SolidityEvmoneInterface: No library set.");
m_compilationFramework.contractName(m_libraryName);
@ -171,10 +171,15 @@ optional<evmc::result> EvmoneUtility::compileAndDeployLibrary()
createResult.status_code == EVMC_SUCCESS,
"SolidityEvmoneInterface: Library deployment failed"
);
auto libraryAt = EVMHost::convertFromEVMC(createResult.create_address);
m_compilationFramework.libraryAddresses(
{{m_libraryName, EVMHost::convertFromEVMC(createResult.create_address)}}
{{m_libraryName, libraryAt}}
);
return createResult;
vector<string> libraryFunctionSelectors;
for (auto const& function: compilationOutput->methodIdentifiersInContract)
libraryFunctionSelectors.push_back(function.asString());
return LibraryStatus{createResult.status_code, libraryAt, libraryFunctionSelectors};
}
else
return nullopt;
@ -187,7 +192,7 @@ optional<evmc::result> EvmoneUtility::compileDeployAndExecute(string _fuzzIsabel
{
auto r = compileAndDeployLibrary();
if (!r.has_value())
return r;
return nullopt;
}
// Stage 2: Compile, deploy, and execute contract, optionally using library
// address map.

View File

@ -218,8 +218,10 @@ public:
/// identifiers for methods in @param _contractName.
std::optional<CompilerOutput> compileContract();
using LibraryStatus = std::tuple<evmc_status_code, solidity::util::h160, std::vector<std::string>>;
/// Compiles and deploys library on blockchain.
std::optional<evmc::result> compileAndDeployLibrary();
std::optional<LibraryStatus> compileAndDeployLibrary();
private:

View File

@ -123,10 +123,12 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
methodName
);
optional<EvmoneUtility::LibraryStatus> libraryInfo;
if (!libraryName.empty()) {
cout << "Deploying library" << endl;
auto l = evmoneUtil.compileAndDeployLibrary();
if (!l.has_value())
libraryInfo = evmoneUtil.compileAndDeployLibrary();
if (!libraryInfo.has_value() || get<0>(libraryInfo.value()) != EVMC_SUCCESS)
return 0;
cout << "Deployed" << endl;
}
@ -135,6 +137,11 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
for (auto const& account: hostContext.accounts)
addressSelector[EVMHost::convertFromEVMC(account.first)] = {};
// Add library functions to address selector
vector<string> libraryFunctionSelectors = get<2>(libraryInfo.value());
if (!libraryFunctionSelectors.empty())
addressSelector[get<1>(libraryInfo.value())] = libraryFunctionSelectors;
auto compilerOutput = evmoneUtil.compileContract();
if (!compilerOutput.has_value())
return 0;
@ -183,17 +190,37 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
// Reset call state post old code gen run
hostContext.reset();
addressSelector.clear();
bool libraryFunctions = !libraryFunctionSelectors.empty();
libraryFunctionSelectors.clear();
evmoneUtil.optSetting(compilerSetting);
evmoneUtil.viaIR(true);
optional<EvmoneUtility::LibraryStatus> libraryInfoNew;
if (!libraryName.empty())
{
auto l = evmoneUtil.compileAndDeployLibrary();
solAssert(l.has_value(), "Deploying library failed for the second time");
libraryInfoNew = evmoneUtil.compileAndDeployLibrary();
solAssert(
libraryInfoNew.has_value() && get<0>(libraryInfoNew.value()) == EVMC_SUCCESS,
"Deploying library failed for the second time"
);
}
for (auto const& account: hostContext.accounts)
addressSelector[EVMHost::convertFromEVMC(account.first)] = {};
libraryFunctionSelectors = get<2>(libraryInfoNew.value());
// Library functions in both runs should either be both empty or
// both non-empty.
solAssert(
(
(libraryFunctions && !libraryFunctionSelectors.empty()) ||
(!libraryFunctions && libraryFunctionSelectors.empty())
),
"Library function mismatch."
);
if (!libraryFunctionSelectors.empty())
addressSelector[get<1>(libraryInfoNew.value())] = libraryFunctionSelectors;
auto compilerOutputOpt = evmoneUtil.compileContract();
solAssert(compilerOutputOpt.has_value(), "Contract could not be optimised.");