/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see .
*/
#include
#include
#include
using namespace std;
using namespace yul::test::yul_fuzzer;
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Literal const& _x)
{
switch (_x.literal_oneof_case())
{
case Literal::kIntval:
_os << _x.intval();
break;
case Literal::LITERAL_ONEOF_NOT_SET:
_os << "1";
break;
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, VarRef const& _x)
{
return _os << "x_" << (static_cast(_x.varnum()) % 10);
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Expression const& _x)
{
switch (_x.expr_oneof_case())
{
case Expression::kVarref:
_os << _x.varref();
break;
case Expression::kCons:
_os << _x.cons();
break;
case Expression::kBinop:
_os << _x.binop();
break;
case Expression::kUnop:
_os << _x.unop();
break;
case Expression::EXPR_ONEOF_NOT_SET:
_os << "1";
break;
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, BinaryOp const& _x)
{
switch (_x.op())
{
case BinaryOp::ADD:
_os << "add";
break;
case BinaryOp::SUB:
_os << "sub";
break;
case BinaryOp::MUL:
_os << "mul";
break;
case BinaryOp::DIV:
_os << "div";
break;
case BinaryOp::MOD:
_os << "mod";
break;
case BinaryOp::XOR:
_os << "xor";
break;
case BinaryOp::AND:
_os << "and";
break;
case BinaryOp::OR:
_os << "or";
break;
case BinaryOp::EQ:
_os << "eq";
break;
case BinaryOp::LT:
_os << "lt";
break;
case BinaryOp::GT:
_os << "gt";
break;
case BinaryOp::SHR:
_os << "shr";
break;
case BinaryOp::SHL:
_os << "shl";
break;
case BinaryOp::SAR:
_os << "sar";
break;
case BinaryOp::SDIV:
_os << "sdiv";
break;
case BinaryOp::SMOD:
_os << "smod";
break;
case BinaryOp::EXP:
_os << "exp";
break;
case BinaryOp::SLT:
_os << "slt";
break;
case BinaryOp::SGT:
_os << "sgt";
break;
case BinaryOp::BYTE:
_os << "byte";
break;
case BinaryOp::SI:
_os << "signextend";
break;
case BinaryOp::KECCAK:
_os << "keccak256";
break;
}
return _os << "(" << _x.left() << "," << _x.right() << ")";
}
// New var numbering starts from x_10 until x_16
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, VarDecl const& _x)
{
return _os << "let x_" << ((_x.id() % 7) + 10) << " := " << _x.expr() << "\n";
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, TypedVarDecl const& _x)
{
_os << "let x_" << ((_x.id() % 7) + 10);
switch (_x.type())
{
case TypedVarDecl::BOOL:
_os << ": bool := " << _x.expr() << " : bool\n";
break;
case TypedVarDecl::S8:
_os << ": s8 := " << _x.expr() << " : s8\n";
break;
case TypedVarDecl::S32:
_os << ": s32 := " << _x.expr() << " : s32\n";
break;
case TypedVarDecl::S64:
_os << ": s64 := " << _x.expr() << " : s64\n";
break;
case TypedVarDecl::S128:
_os << ": s128 := " << _x.expr() << " : s128\n";
break;
case TypedVarDecl::S256:
_os << ": s256 := " << _x.expr() << " : s256\n";
break;
case TypedVarDecl::U8:
_os << ": u8 := " << _x.expr() << " : u8\n";
break;
case TypedVarDecl::U32:
_os << ": u32 := " << _x.expr() << " : u32\n";
break;
case TypedVarDecl::U64:
_os << ": u64 := " << _x.expr() << " : u64\n";
break;
case TypedVarDecl::U128:
_os << ": u128 := " << _x.expr() << " : u128\n";
break;
case TypedVarDecl::U256:
_os << ": u256 := " << _x.expr() << " : u256\n";
break;
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, UnaryOp const& _x)
{
switch (_x.op())
{
case UnaryOp::NOT:
_os << "not";
break;
case UnaryOp::MLOAD:
_os << "mload";
break;
case UnaryOp::SLOAD:
_os << "sload";
break;
case UnaryOp::ISZERO:
_os << "iszero";
break;
}
return _os << "(" << _x.operand() << ")";
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, AssignmentStatement const& _x)
{
return _os << _x.ref_id() << " := " << _x.expr() << "\n";
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, IfStmt const& _x)
{
return _os <<
"if " <<
_x.cond() <<
" " <<
_x.if_body();
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, StoreFunc const& _x)
{
switch (_x.st())
{
case StoreFunc::MSTORE:
_os << "mstore(" << _x.loc() << ", " << _x.val() << ")\n";
break;
case StoreFunc::SSTORE:
_os << "sstore(" << _x.loc() << ", " << _x.val() << ")\n";
break;
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, ForStmt const& _x)
{
_os << "for { let i := 0 } lt(i, 0x100) { i := add(i, 0x20) } ";
return _os << _x.for_body();
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, CaseStmt const& _x)
{
_os << "case " << _x.case_lit() << " ";
return _os << _x.case_block();
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, SwitchStmt const& _x)
{
if (_x.case_stmt_size() > 0 || _x.has_default_block())
{
_os << "switch " << _x.switch_expr() << "\n";
for (auto const& caseStmt: _x.case_stmt())
_os << caseStmt;
if (_x.has_default_block())
_os << "default " << _x.default_block();
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Statement const& _x)
{
switch (_x.stmt_oneof_case())
{
case Statement::kDecl:
_os << _x.decl();
break;
case Statement::kAssignment:
_os << _x.assignment();
break;
case Statement::kIfstmt:
_os << _x.ifstmt();
break;
case Statement::kStorageFunc:
_os << _x.storage_func();
break;
case Statement::kBlockstmt:
_os << _x.blockstmt();
break;
case Statement::kForstmt:
_os << _x.forstmt();
break;
case Statement::kSwitchstmt:
_os << _x.switchstmt();
break;
case Statement::STMT_ONEOF_NOT_SET:
break;
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Block const& _x)
{
if (_x.statements_size() > 0)
{
_os << "{\n";
for (auto const& st: _x.statements())
_os << st;
_os << "}\n";
}
else
{
_os << "{}\n";
}
return _os;
}
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Function const& _x)
{
_os << "{\n"
<< "let a,b := foo(calldataload(0),calldataload(32),calldataload(64),calldataload(96),calldataload(128),"
<< "calldataload(160),calldataload(192),calldataload(224))\n"
<< "sstore(0, a)\n"
<< "sstore(32, b)\n"
<< "function foo(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7) -> x_8, x_9\n"
<< _x.statements()
<< "}\n";
return _os;
}
string yul::test::yul_fuzzer::functionToString(Function const& _input)
{
ostringstream os;
os << _input;
return os.str();
}
string yul::test::yul_fuzzer::protoToYul(const uint8_t* _data, size_t _size)
{
Function message;
if (!message.ParsePartialFromArray(_data, _size))
return "#error invalid proto\n";
return functionToString(message);
}