mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Initial commit
This commit is contained in:
parent
1bb65f80ef
commit
49cda44699
@ -27,8 +27,10 @@ if (OSSFUZZ)
|
||||
solc_ossfuzz.cpp
|
||||
../fuzzer_common.cpp
|
||||
../../TestCaseReader.cpp
|
||||
../../EVMHost.cpp
|
||||
SolidityEvmoneInterface.cpp
|
||||
)
|
||||
target_link_libraries(solc_ossfuzz PRIVATE libsolc evmasm)
|
||||
target_link_libraries(solc_ossfuzz PRIVATE libsolc evmasm evmc evmone-standalone)
|
||||
set_target_properties(solc_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_mutator_ossfuzz
|
||||
|
@ -65,6 +65,15 @@ optional<CompilerOutput> SolidityCompilationFramework::compileContract()
|
||||
}
|
||||
}
|
||||
|
||||
optional<string> SolidityCompilationFramework::noInputFunction()
|
||||
{
|
||||
Json::Value const& contractABI = m_compiler.contractABI(m_compiler.lastContractName());
|
||||
for (auto const& functionABI: contractABI)
|
||||
if (functionABI["inputs"].size() == 0)
|
||||
return functionABI["name"].asString() + "()";
|
||||
return {};
|
||||
}
|
||||
|
||||
bool EvmoneUtility::zeroWord(uint8_t const* _result, size_t _length)
|
||||
{
|
||||
return _length == 32 &&
|
||||
|
@ -97,6 +97,14 @@ public:
|
||||
/// method identifiers in contract if compilation is successful,
|
||||
/// null value otherwise.
|
||||
std::optional<CompilerOutput> compileContract();
|
||||
/// @returns name of a public/external method that does not contain
|
||||
/// input parameters in its signature.
|
||||
std::optional<std::string> noInputFunction();
|
||||
/// @returns name of the last contract in source unit.
|
||||
std::string lastContractName()
|
||||
{
|
||||
return m_compiler.lastContractName();
|
||||
}
|
||||
private:
|
||||
frontend::CompilerStack m_compiler;
|
||||
CompilerInput m_compilerInput;
|
||||
@ -134,7 +142,27 @@ public:
|
||||
/// don't run into out of gas errors. The input field is copied from
|
||||
/// @param _input.
|
||||
static evmc_message initializeMessage(bytes const& _input);
|
||||
private:
|
||||
/// Sets method name to @param _methodName.
|
||||
void methodName(std::string _methodName)
|
||||
{
|
||||
m_methodName = _methodName;
|
||||
}
|
||||
// Sets method name to @param _contractName.
|
||||
void contractName(std::string _contractName)
|
||||
{
|
||||
m_contractName = _contractName;
|
||||
m_compilationFramework.contractName(_contractName);
|
||||
}
|
||||
void lastContract()
|
||||
{
|
||||
m_contractName = m_compilationFramework.lastContractName();
|
||||
m_compilationFramework.contractName(m_contractName);
|
||||
}
|
||||
std::optional<std::string> noInputFunction()
|
||||
{
|
||||
return m_compilationFramework.noInputFunction();
|
||||
}
|
||||
|
||||
/// @returns the result of the execution of the function whose
|
||||
/// keccak256 hash is @param _functionHash that is deployed at
|
||||
/// @param _deployedAddress in @param _hostContext.
|
||||
@ -159,6 +187,8 @@ private:
|
||||
/// identifiers for methods in @param _contractName.
|
||||
std::optional<CompilerOutput> compileContract();
|
||||
|
||||
private:
|
||||
|
||||
/// EVM Host implementation
|
||||
solidity::test::EVMHost& m_evmHost;
|
||||
/// Solidity compilation framework
|
||||
|
@ -18,43 +18,101 @@
|
||||
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
|
||||
#include <test/tools/ossfuzz/SolidityEvmoneInterface.h>
|
||||
|
||||
#include <test/TestCaseReader.h>
|
||||
|
||||
#include <evmone/evmone.h>
|
||||
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace solidity::frontend::test;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::test::fuzzer;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::test;
|
||||
using namespace std;
|
||||
|
||||
// Prototype as we can't use the FuzzerInterface.h header.
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size);
|
||||
|
||||
static evmc::VM evmone = evmc::VM{evmc_create_evmone()};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
{
|
||||
if (_size <= 600)
|
||||
{
|
||||
string input(reinterpret_cast<char const*>(_data), _size);
|
||||
// TODO: Cannot fuzz tests containing libraries yet.
|
||||
if (input.find("library") != string::npos)
|
||||
return 0;
|
||||
|
||||
map<string, string> sourceCode;
|
||||
try
|
||||
{
|
||||
EVMVersion version;
|
||||
EVMHost hostContext(version, evmone);
|
||||
|
||||
TestCaseReader t = TestCaseReader(std::istringstream(input));
|
||||
sourceCode = t.sources().sources;
|
||||
map<string, string> settings = t.settings();
|
||||
bool compileViaYul =
|
||||
settings.count("compileViaYul") &&
|
||||
(settings.at("compileViaYul") == "also" || settings.at("compileViaYul") == "true");
|
||||
bool optimize = settings.count("optimize") && settings.at("optimize") == "true";
|
||||
FuzzerUtil::testCompiler(
|
||||
string contractName;
|
||||
string methodName;
|
||||
auto compilerSetting = OptimiserSettings::standard();
|
||||
CompilerInput cInput = {
|
||||
version,
|
||||
sourceCode,
|
||||
optimize,
|
||||
/*_rand=*/static_cast<unsigned>(_size),
|
||||
/*forceSMT=*/true,
|
||||
compileViaYul
|
||||
contractName,
|
||||
compilerSetting,
|
||||
{},
|
||||
false,
|
||||
false
|
||||
};
|
||||
EvmoneUtility evmoneUtil(
|
||||
hostContext,
|
||||
cInput,
|
||||
contractName,
|
||||
{},
|
||||
methodName
|
||||
);
|
||||
|
||||
auto compilerOutput = evmoneUtil.compileContract();
|
||||
if (!compilerOutput.has_value())
|
||||
return 0;
|
||||
|
||||
optional<string> noInputFunction = evmoneUtil.noInputFunction();
|
||||
if (noInputFunction.has_value())
|
||||
evmoneUtil.methodName(noInputFunction.value());
|
||||
else
|
||||
return 0;
|
||||
|
||||
auto deployResult = evmoneUtil.deployContract(compilerOutput->byteCode);
|
||||
if (deployResult.status_code != EVMC_SUCCESS)
|
||||
return 0;
|
||||
|
||||
auto callResult = evmoneUtil.executeContract(
|
||||
solidity::util::fromHex(compilerOutput->methodIdentifiersInContract[noInputFunction.value()].asString()),
|
||||
deployResult.create_address
|
||||
);
|
||||
|
||||
if (callResult.status_code != EVMC_SUCCESS)
|
||||
return 0;
|
||||
|
||||
solidity::bytes result;
|
||||
for (size_t i = 0; i < callResult.output_size; i++)
|
||||
result.push_back(callResult.output_data[i]);
|
||||
|
||||
cout << solidity::util::toHex(result) << endl;
|
||||
}
|
||||
catch (runtime_error const&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
catch (solidity::langutil::UnimplementedFeatureError const&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user