Skip to content

Commit

Permalink
Abiv2 fuzzer: Enable differential fuzzing and remove support for stri…
Browse files Browse the repository at this point in the history
…ng coding

co-authored-by: Leonardo <[email protected]>
  • Loading branch information
bshastry and Leonardo committed Dec 15, 2020
1 parent 39f1893 commit b273e52
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 37 deletions.
58 changes: 55 additions & 3 deletions test/tools/ossfuzz/AbiV2IsabelleFuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
2 changes: 1 addition & 1 deletion test/tools/ossfuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 2 additions & 8 deletions test/tools/ossfuzz/abiV2Proto.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 3 additions & 13 deletions test/tools/ossfuzz/protoToAbiV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 4 additions & 12 deletions test/tools/ossfuzz/protoToAbiV2.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ class ProtoConverter
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
{
Expand Down Expand Up @@ -448,7 +452,6 @@ class AbiV2ProtoVisitor
enum class DataType
{
BYTES,
STRING,
VALUE,
ARRAY
};
Expand Down Expand Up @@ -537,17 +540,6 @@ class AbiV2ProtoVisitor
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)
{
Expand Down

0 comments on commit b273e52

Please sign in to comment.