mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Abiv2 fuzzer: Enable differential fuzzing and remove support for string coding
co-authored-by: Leonardo <leo@ethereum.org>
This commit is contained in:
parent
39f1893956
commit
b273e52628
@ -24,9 +24,14 @@
|
||||
|
||||
using namespace solidity::test::abiv2fuzzer;
|
||||
using namespace solidity::test;
|
||||
using namespace solidity::util;
|
||||
using namespace solidity;
|
||||
using namespace std;
|
||||
|
||||
static constexpr size_t abiCoderHeapSize = 1024 * 512;
|
||||
static evmc::VM evmone = evmc::VM{evmc_create_evmone()};
|
||||
/// Expected output value is decimal 0
|
||||
static vector<uint8_t> const expectedOutput(32, 0);
|
||||
|
||||
DEFINE_PROTO_FUZZER(Contract const& _contract)
|
||||
{
|
||||
@ -43,13 +48,60 @@ DEFINE_PROTO_FUZZER(Contract const& _contract)
|
||||
|
||||
string typeString = converter.isabelleTypeString();
|
||||
string valueString = converter.isabelleValueString();
|
||||
std::cout << typeString << std::endl;
|
||||
std::cout << valueString << std::endl;
|
||||
abicoder::ABICoder coder(abiCoderHeapSize);
|
||||
if (!typeString.empty())
|
||||
if (!typeString.empty() && converter.coderFunction())
|
||||
{
|
||||
auto [encodeStatus, encodedData] = coder.encode(typeString, valueString);
|
||||
solAssert(encodeStatus, "Isabelle abicoder fuzzer: Encoding failed");
|
||||
|
||||
// Raw runtime byte code generated by solidity
|
||||
bytes byteCode;
|
||||
string hexEncodedInput;
|
||||
|
||||
try
|
||||
{
|
||||
// Compile contract generated by the proto fuzzer
|
||||
SolidityCompilationFramework solCompilationFramework;
|
||||
string contractName = ":C";
|
||||
byteCode = solCompilationFramework.compileContract(contractSource, contractName);
|
||||
Json::Value methodIdentifiers = solCompilationFramework.getMethodIdentifiers();
|
||||
// We always call the second function from the list of alphabetically
|
||||
// sorted interface functions
|
||||
hexEncodedInput = (++methodIdentifiers.begin())->asString() + encodedData.substr(2, encodedData.size());
|
||||
}
|
||||
// Ignore stack too deep errors during compilation
|
||||
catch (solidity::evmasm::StackTooDeepException const&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We target the default EVM which is the latest
|
||||
solidity::langutil::EVMVersion version;
|
||||
EVMHost hostContext(version, evmone);
|
||||
|
||||
// Deploy contract and signal failure if deployment failed
|
||||
evmc::result createResult = AbiV2Utility::deployContract(hostContext, byteCode);
|
||||
solAssert(
|
||||
createResult.status_code == EVMC_SUCCESS,
|
||||
"Proto ABIv2 Fuzzer: Contract creation failed"
|
||||
);
|
||||
|
||||
// Execute test function and signal failure if EVM reverted or
|
||||
// did not return expected output on successful execution.
|
||||
evmc::result callResult = AbiV2Utility::executeContract(
|
||||
hostContext,
|
||||
fromHex(hexEncodedInput),
|
||||
createResult.create_address
|
||||
);
|
||||
|
||||
// We don't care about EVM One failures other than EVMC_REVERT
|
||||
solAssert(callResult.status_code != EVMC_REVERT, "Proto ABIv2 fuzzer: EVM One reverted");
|
||||
if (callResult.status_code == EVMC_SUCCESS)
|
||||
solAssert(
|
||||
AbiV2Utility::isOutputExpected(callResult.output_data, callResult.output_size, expectedOutput),
|
||||
"Proto ABIv2 fuzzer: ABIv2 coding failure found"
|
||||
);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ if (OSSFUZZ)
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
abicoder
|
||||
gmp
|
||||
gmp.a
|
||||
)
|
||||
set_target_properties(abiv2_isabelle_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
target_compile_options(abiv2_isabelle_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion -Wno-suggest-destructor-override -Wno-inconsistent-missing-destructor-override)
|
||||
|
@ -44,14 +44,8 @@ message ValueType {
|
||||
}
|
||||
}
|
||||
|
||||
// bytes/string
|
||||
message DynamicByteArrayType {
|
||||
enum DType {
|
||||
BYTES = 0;
|
||||
STRING = 1;
|
||||
}
|
||||
required DType type = 1;
|
||||
}
|
||||
// bytes
|
||||
message DynamicByteArrayType {}
|
||||
|
||||
message ArrayType {
|
||||
required Type t = 1;
|
||||
|
@ -830,10 +830,10 @@ string TypeVisitor::visit(ArrayType const& _type)
|
||||
return baseType + arrayBracket;
|
||||
}
|
||||
|
||||
string TypeVisitor::visit(DynamicByteArrayType const& _type)
|
||||
string TypeVisitor::visit(DynamicByteArrayType const&)
|
||||
{
|
||||
m_isLastDynParamRightPadded = true;
|
||||
m_baseType = bytesArrayTypeAsString(_type);
|
||||
m_baseType = "bytes";
|
||||
m_structTupleString.addTypeStringToTuple(m_baseType);
|
||||
return m_baseType;
|
||||
}
|
||||
@ -967,7 +967,7 @@ pair<string, string> AssignCheckVisitor::visit(DynamicByteArrayType const& _type
|
||||
string isabelleValue = ValueGetterVisitor{}.isabelleBytesValueAsString(value);
|
||||
m_valueStream.appendValue(isabelleValue);
|
||||
}
|
||||
DataType dataType = _type.type() == DynamicByteArrayType::BYTES ? DataType::BYTES : DataType::STRING;
|
||||
DataType dataType = DataType::BYTES;
|
||||
return assignAndCheckStringPair(m_varName, m_paramName, value, value, dataType);
|
||||
}
|
||||
|
||||
@ -1127,12 +1127,6 @@ string AssignCheckVisitor::checkString(string const& _ref, string const& _value,
|
||||
string checkPred;
|
||||
switch (_type)
|
||||
{
|
||||
case DataType::STRING:
|
||||
checkPred = Whiskers(R"(!bytesCompare(bytes(<varName>), <value>))")
|
||||
("varName", _ref)
|
||||
("value", _value)
|
||||
.render();
|
||||
break;
|
||||
case DataType::BYTES:
|
||||
checkPred = Whiskers(R"(!bytesCompare(<varName>, <value>))")
|
||||
("varName", _ref)
|
||||
@ -1288,10 +1282,6 @@ std::string ValueGetterVisitor::variableLengthValueAsString(
|
||||
bool _isHexLiteral
|
||||
)
|
||||
{
|
||||
// TODO: Move this to caller
|
||||
// solAssert(_numBytes >= 0 && _numBytes <= s_maxDynArrayLength,
|
||||
// "Proto ABIv2 fuzzer: Invalid hex length"
|
||||
// );
|
||||
if (_numBytes == 0)
|
||||
return Whiskers(R"(<?isHex>hex</isHex>"")")
|
||||
("isHex", _isHexLiteral)
|
||||
|
@ -154,6 +154,10 @@ public:
|
||||
std::string contractToString(Contract const& _input);
|
||||
std::string isabelleTypeString() const;
|
||||
std::string isabelleValueString() const;
|
||||
bool coderFunction() const
|
||||
{
|
||||
return m_test == Contract_Test::Contract_Test_CALLDATA_CODER;
|
||||
}
|
||||
private:
|
||||
enum class Delimiter
|
||||
{
|
||||
@ -448,7 +452,6 @@ public:
|
||||
enum class DataType
|
||||
{
|
||||
BYTES,
|
||||
STRING,
|
||||
VALUE,
|
||||
ARRAY
|
||||
};
|
||||
@ -537,17 +540,6 @@ public:
|
||||
else
|
||||
return v;
|
||||
}
|
||||
|
||||
static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x)
|
||||
{
|
||||
switch (_x.type())
|
||||
{
|
||||
case DynamicByteArrayType::BYTES:
|
||||
return "bytes";
|
||||
case DynamicByteArrayType::STRING:
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
protected:
|
||||
T visitValueType(ValueType const& _type)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user