Permit u256 constants

This commit is contained in:
Bhargava Shastry 2020-05-04 15:31:06 +02:00
parent 97f94fdcc6
commit 9bfab1fe00
4 changed files with 69 additions and 40 deletions

View File

@ -37,6 +37,7 @@ namespace solidity::langutil
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
struct FuzzerError: virtual util::Exception {};
struct CompilerError: virtual util::Exception {};
struct InternalCompilerError: virtual util::Exception {};
struct FatalError: virtual util::Exception {};

View File

@ -123,9 +123,9 @@ std::pair<bytes, Json::Value> compileContract(
);
}
// Ignore stack too deep errors during compilation
catch (evmasm::StackTooDeepException const&)
catch (Exception const&)
{
return std::make_pair(bytes{}, Json::Value(0));
throw langutil::FuzzerError();
}
}
@ -225,31 +225,37 @@ DEFINE_PROTO_FUZZER(Program const& _input)
std::cout << sol_source << std::endl;
}
auto minimalResult = compileDeployAndExecute(
sol_source,
":C",
"test()",
frontend::OptimiserSettings::minimal(),
""
);
bool successState = minimalResult.status_code == EVMC_SUCCESS;
try {
auto minimalResult = compileDeployAndExecute(
sol_source,
":C",
"test()",
frontend::OptimiserSettings::minimal(),
""
);
bool successState = minimalResult.status_code == EVMC_SUCCESS;
auto optResult = compileDeployAndExecute(
sol_source,
":C",
"test()",
frontend::OptimiserSettings::standard(),
""
);
if (successState)
{
solAssert(
optResult.status_code == EVMC_SUCCESS,
"Sol arith fuzzer: Optimal code failed"
);
solAssert(
compareRuns(minimalResult, optResult),
"Sol arith fuzzer: Runs produced different result"
auto optResult = compileDeployAndExecute(
sol_source,
":C",
"test()",
frontend::OptimiserSettings::standard(),
""
);
if (successState)
{
solAssert(
optResult.status_code == EVMC_SUCCESS,
"Sol arith fuzzer: Optimal code failed"
);
solAssert(
compareRuns(minimalResult, optResult),
"Sol arith fuzzer: Runs produced different result"
);
}
}
catch (langutil::FuzzerError const&)
{
}
}

View File

@ -84,7 +84,7 @@ string ProtoConverter::visit(VarDecl const& _vardecl)
m_varTypeMap.emplace(varName, pair(typeSign(_vardecl.t()), type));
v("type", type);
v("varName", varName);
v("value", varExists ? visit(_vardecl.value()) : to_string((*m_rand)()));
v("value", varExists ? visit(_vardecl.value()) : maskUnsignedToHex(64));
incrementVarCounter();
return "\t\t" + v.render() + '\n';
}
@ -142,19 +142,19 @@ string ProtoConverter::visit(BinaryOp const& _bop)
auto left = visit(_bop.left());
auto right = visit(_bop.right());
Sign leftSign = m_exprSignMap[&_bop.left()];
Sign rightSign = m_exprSignMap[&_bop.right()];
Sign leftSign = m_exprSignMap[&_bop.left()].first;
string leftSignString = m_exprSignMap[&_bop.left()].second;
Sign rightSign = m_exprSignMap[&_bop.right()].first;
string rightSignString = m_exprSignMap[&_bop.right()].second;
bool expSignChange = _bop.op() == BinaryOp_Op_EXP && rightSign == Sign::Signed;
bool expOrMod = binaryOperandExp(_bop.op());
bool expSignChange = expOrMod && rightSign == Sign::Signed;
if (expSignChange)
{
right = Whiskers(R"(uint(<expr>))")("expr", right).render();
rightSign = Sign::Unsigned;
}
if (leftSign != rightSign && _bop.op() != BinaryOp_Op_EXP)
right = signString(leftSign) + "(" + right + ")";
else if (!expOrMod || leftSign == Sign::Unsigned)
right = leftSignString + "(" + right + ")";
return left + op + right;
return '(' + left + op + right + ')';
}
string ProtoConverter::visit(Expression const& _expr)
@ -166,7 +166,7 @@ string ProtoConverter::visit(Expression const& _expr)
solAssert(varAvailable(), "Sol arith fuzzer: Varref unavaileble");
string v = visit(_expr.v());
if (!m_exprSignMap.count(&_expr))
m_exprSignMap.emplace(&_expr, m_varTypeMap[v].first);
m_exprSignMap.emplace(&_expr, m_varTypeMap[v]);
return v;
}
case Expression::kBop:
@ -179,8 +179,9 @@ string ProtoConverter::visit(Expression const& _expr)
}
case Expression::EXPR_ONEOF_NOT_SET:
{
m_exprSignMap.emplace(&_expr, m_varTypeMap["v0"].first);
return "v0";
if (!m_exprSignMap.count(&_expr))
m_exprSignMap.emplace(&_expr, pair(Sign::Unsigned, "uint"));
return maskUnsignedToHex(64);
}
}
}

View File

@ -1,5 +1,8 @@
#include <test/tools/ossfuzz/solArith.pb.h>
#include <libsolutil/Common.h>
#include <libsolutil/FixedHash.h>
#include <libsolutil/Keccak256.h>
#include <random>
namespace solidity::test::solarithfuzzer
@ -109,11 +112,29 @@ private:
{
return _ts.s() == Type::SIGNED ? Sign::Signed : Sign::Unsigned;
}
std::string maskUnsignedToHex(unsigned _numMaskNibbles)
{
return toHex(maskUnsignedInt(_numMaskNibbles), util::HexPrefix::Add);
}
bool binaryOperandExp(BinaryOp::Op _op)
{
return _op == BinaryOp_Op_EXP;
}
// Convert _counter to string and return its keccak256 hash
solidity::u256 hashUnsignedInt()
{
return util::keccak256(util::h256((*m_rand)()));
}
u256 maskUnsignedInt(unsigned _numMaskNibbles)
{
return hashUnsignedInt() & u256("0x" + std::string(_numMaskNibbles, 'f'));
}
unsigned m_varCounter = 0;
std::shared_ptr<SolRandomNumGenerator> m_rand;
std::map<std::string, std::pair<Sign, std::string>> m_varTypeMap;
std::map<Expression const*, Sign> m_exprSignMap;
std::map<Expression const*, std::pair<Sign, std::string>> m_exprSignMap;
std::string m_returnType;
};
}