[ci skip] Add magic expressions such as keccak256/ripemd etc.

This commit is contained in:
Bhargava Shastry 2021-06-14 13:26:59 +02:00
parent 66ee8a647e
commit 3481a402d7
2 changed files with 326 additions and 31 deletions

View File

@ -942,30 +942,126 @@ optional<pair<SolidityTypePtr, string>> ExpressionGenerator::incDecOperation(
return lResult; return lResult;
} }
optional<pair<SolidityTypePtr, string>> ExpressionGenerator::memberAccessExpr( pair<SolidityTypePtr, string> ExpressionGenerator::memberAccessExpr(SolidityTypePtr& _type)
pair<SolidityTypePtr, string>& _typeName
)
{ {
solAssert( solAssert(
holds_alternative<shared_ptr<IntegerType>>(_typeName.first) || holds_alternative<shared_ptr<IntegerType>>(_type) ||
holds_alternative<shared_ptr<BytesType>>(_typeName.first) || holds_alternative<shared_ptr<BytesType>>(_type) ||
holds_alternative<shared_ptr<FixedBytesType>>(_typeName.first), holds_alternative<shared_ptr<FixedBytesType>>(_type),
"" ""
); );
ExpressionGenerator exprGen{state};
auto addressType = make_shared<AddressType>(); auto addressType = make_shared<AddressType>();
pair<SolidityTypePtr, string> addressTypeName = {addressType, {}}; pair<SolidityTypePtr, string> addressTypeName = {addressType, {}};
auto expression = exprGen.rLValueOrLiteral(addressTypeName); auto expression = rLValueOrLiteral(addressTypeName);
exprGen.resetNestingDepth();
solAssert(expression.has_value(), ""); solAssert(expression.has_value(), "");
// TODO: Clean this up // TODO: Clean this up
if (holds_alternative<shared_ptr<IntegerType>>(_typeName.first)) if (holds_alternative<shared_ptr<IntegerType>>(_type))
expression.value().second += ".balance"; expression.value().second += ".balance";
else if (holds_alternative<shared_ptr<FixedBytesType>>(_typeName.first)) else if (holds_alternative<shared_ptr<BytesType>>(_type))
expression.value().second += ".codehash"; expression.value().second += ".codehash";
else else
expression.value().second += ".code"; expression.value().second += ".code";
return expression; return expression.value();
}
pair<SolidityTypePtr, string> ExpressionGenerator::magicExpr(SolidityTypePtr& _type)
{
solAssert(
holds_alternative<shared_ptr<IntegerType>>(_type) ||
holds_alternative<shared_ptr<AddressType>>(_type) ||
holds_alternative<shared_ptr<FixedBytesType>>(_type),
""
);
if (holds_alternative<shared_ptr<IntegerType>>(_type))
{
auto integerType = get<shared_ptr<IntegerType>>(_type);
solAssert(!integerType->signedType && integerType->numBits == 256, "");
auto paramIntType = make_shared<IntegerType>(IntegerType::Bits::B256, false);
pair<SolidityTypePtr, string> paramIntTypeName = {paramIntType, {}};
auto x = rLValueOrLiteral(paramIntTypeName);
auto y = rLValueOrLiteral(paramIntTypeName);
auto k = rLValueOrLiteral(paramIntTypeName);
solAssert(x.has_value() && y.has_value() && k.has_value(), "");
string builtin;
if (state->uRandDist->probable(2))
builtin = "addmod";
else
builtin = "mulmod";
auto builtinExpr = builtin +
"(" +
x.value().second +
", " +
y.value().second +
", " +
k.value().second +
")";
return pair<SolidityTypePtr, string>(paramIntType, builtinExpr);
}
else if (holds_alternative<shared_ptr<AddressType>>(_type))
{
// ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
auto bytes32Type = make_shared<FixedBytesType>(FixedBytesType::Bytes::W32);
auto uint8Type = make_shared<IntegerType>(IntegerType::Bits::B8, false);
pair<SolidityTypePtr, string> paramBytes32TypeName = {bytes32Type, {}};
pair<SolidityTypePtr, string> paramUint8TypeName = {uint8Type, {}};
auto hash = rLValueOrLiteral(paramBytes32TypeName);
auto r = rLValueOrLiteral(paramBytes32TypeName);
auto s = rLValueOrLiteral(paramBytes32TypeName);
auto v = rLValueOrLiteral(paramUint8TypeName);
solAssert(hash.has_value() && r.has_value() && s.has_value() && v.has_value(), "");
string builtinExpr = string("ecrecover") +
"(" +
hash.value().second +
", " +
v.value().second +
", " +
r.value().second +
", " +
s.value().second +
")";
auto addressType = make_shared<AddressType>();
return pair<SolidityTypePtr, string>(addressType, builtinExpr);
}
else if (holds_alternative<shared_ptr<FixedBytesType>>(_type))
{
auto fixedBytesType = get<shared_ptr<FixedBytesType>>(_type);
if (fixedBytesType->numBytes == 20)
{
// ripemd160(bytes memory) returns (bytes20)
auto bytes20Type = make_shared<FixedBytesType>(FixedBytesType::Bytes::W20);
auto bytesType = make_shared<BytesType>();
pair<SolidityTypePtr, string> paramBytesTypeName = {bytesType, {}};
auto mem = rLValueOrLiteral(paramBytesTypeName);
solAssert(mem.has_value(), "");
string ripemdExpr = string("ripemd160") +
"(" +
mem.value().second +
")";
return pair<SolidityTypePtr, string>(bytes20Type, ripemdExpr);
}
else
{
solAssert(fixedBytesType->numBytes == 32, "");
auto bytes32Type = make_shared<FixedBytesType>(FixedBytesType::Bytes::W32);
auto bytesType = make_shared<BytesType>();
pair<SolidityTypePtr, string> paramBytesTypeName = {bytesType, {}};
auto mem = rLValueOrLiteral(paramBytesTypeName);
solAssert(mem.has_value(), "");
// sha256(bytes memory) returns (bytes32)
// keccak256(bytes memory) returns (bytes32)
string builtin;
if (state->uRandDist->probable(2))
builtin = "sha256";
else
builtin = "keccak256";
string builtinExpr = builtin +
"(" +
mem.value().second +
")";
return pair<SolidityTypePtr, string>(bytes32Type, builtinExpr);
}
}
solAssert(false, "");
} }
ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTypePtr& _typePtr) ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTypePtr& _typePtr)
@ -973,7 +1069,6 @@ ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTyp
vector<RLValueExpr> permittedTypes; vector<RLValueExpr> permittedTypes;
if (holds_alternative<shared_ptr<BoolType>>(_typePtr)) if (holds_alternative<shared_ptr<BoolType>>(_typePtr))
{
permittedTypes = { permittedTypes = {
RLValueExpr::VARREF, RLValueExpr::VARREF,
RLValueExpr::LIT, RLValueExpr::LIT,
@ -987,7 +1082,6 @@ ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTyp
RLValueExpr::AND, RLValueExpr::AND,
RLValueExpr::OR RLValueExpr::OR
}; };
}
else if (holds_alternative<shared_ptr<FixedBytesType>>(_typePtr)) else if (holds_alternative<shared_ptr<FixedBytesType>>(_typePtr))
{ {
permittedTypes = { permittedTypes = {
@ -999,7 +1093,12 @@ ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTyp
}; };
auto bytesType = get<shared_ptr<FixedBytesType>>(_typePtr); auto bytesType = get<shared_ptr<FixedBytesType>>(_typePtr);
if (bytesType->numBytes == 32) if (bytesType->numBytes == 32)
{
permittedTypes.emplace_back(RLValueExpr::MEMBERACCESS); permittedTypes.emplace_back(RLValueExpr::MEMBERACCESS);
permittedTypes.emplace_back(RLValueExpr::MAGICEXPR);
}
else if (bytesType->numBytes == 20)
permittedTypes.emplace_back(RLValueExpr::MAGICEXPR);
} }
else if (holds_alternative<shared_ptr<IntegerType>>(_typePtr)) else if (holds_alternative<shared_ptr<IntegerType>>(_typePtr))
{ {
@ -1047,21 +1146,22 @@ ExpressionGenerator::RLValueExpr ExpressionGenerator::expressionType(SolidityTyp
RLValueExpr::BITOR RLValueExpr::BITOR
}; };
if (integerType->numBits == 256) if (integerType->numBits == 256)
{
permittedTypes.emplace_back(RLValueExpr::MEMBERACCESS); permittedTypes.emplace_back(RLValueExpr::MEMBERACCESS);
permittedTypes.emplace_back(RLValueExpr::MAGICEXPR);
}
} }
} }
else if (holds_alternative<shared_ptr<BytesType>>(_typePtr)) else if (holds_alternative<shared_ptr<BytesType>>(_typePtr))
{
permittedTypes = { permittedTypes = {
RLValueExpr::VARREF, RLValueExpr::VARREF,
RLValueExpr::LIT, RLValueExpr::LIT,
RLValueExpr::MEMBERACCESS RLValueExpr::MEMBERACCESS
}; };
} else if (holds_alternative<shared_ptr<AddressType>>(_typePtr))
permittedTypes = {RLValueExpr::VARREF, RLValueExpr::LIT, RLValueExpr::MAGICEXPR};
else else
{
permittedTypes = {RLValueExpr::VARREF, RLValueExpr::LIT}; permittedTypes = {RLValueExpr::VARREF, RLValueExpr::LIT};
}
return permittedTypes[state->uRandDist->distributionOneToN(permittedTypes.size()) - 1]; return permittedTypes[state->uRandDist->distributionOneToN(permittedTypes.size()) - 1];
} }
@ -1369,7 +1469,9 @@ optional<pair<SolidityTypePtr, string>> ExpressionGenerator::rOrLValueExpression
case RLValueExpr::LIT: case RLValueExpr::LIT:
return literal(_typeName.first); return literal(_typeName.first);
case RLValueExpr::MEMBERACCESS: case RLValueExpr::MEMBERACCESS:
return memberAccessExpr(_typeName); return memberAccessExpr(_typeName.first);
case RLValueExpr::MAGICEXPR:
return magicExpr(_typeName.first);
default: default:
solAssert(false, ""); solAssert(false, "");
} }
@ -1459,20 +1561,120 @@ SolidityTypePtr TypeProvider::type()
{ {
switch (randomTypeCategory()) switch (randomTypeCategory())
{ {
case Type::INTEGER: case Type::UINT8:
case Type::UINT16:
case Type::UINT24:
case Type::UINT32:
case Type::UINT40:
case Type::UINT48:
case Type::UINT56:
case Type::UINT64:
case Type::UINT72:
case Type::UINT80:
case Type::UINT88:
case Type::UINT96:
case Type::UINT104:
case Type::UINT112:
case Type::UINT120:
case Type::UINT128:
case Type::UINT136:
case Type::UINT144:
case Type::UINT152:
case Type::UINT160:
case Type::UINT168:
case Type::UINT176:
case Type::UINT184:
case Type::UINT192:
case Type::UINT200:
case Type::UINT208:
case Type::UINT216:
case Type::UINT224:
case Type::UINT232:
case Type::UINT240:
case Type::UINT248:
case Type::UINT256:
{ {
IntegerType::Bits b = static_cast<IntegerType::Bits>( IntegerType::Bits b = static_cast<IntegerType::Bits>(
state->uRandDist->distributionOneToN( state->uRandDist->distributionOneToN(
static_cast<size_t>(IntegerType::Bits::B256) static_cast<size_t>(IntegerType::Bits::B256)
) )
); );
// Choose signed/unsigned type with probability of 1/2 = 0.5 return make_shared<IntegerType>(b, false);
bool signedType = state->uRandDist->probable(2); }
return make_shared<IntegerType>(b, signedType); case Type::INT8:
case Type::INT16:
case Type::INT24:
case Type::INT32:
case Type::INT40:
case Type::INT48:
case Type::INT56:
case Type::INT64:
case Type::INT72:
case Type::INT80:
case Type::INT88:
case Type::INT96:
case Type::INT104:
case Type::INT112:
case Type::INT120:
case Type::INT128:
case Type::INT136:
case Type::INT144:
case Type::INT152:
case Type::INT160:
case Type::INT168:
case Type::INT176:
case Type::INT184:
case Type::INT192:
case Type::INT200:
case Type::INT208:
case Type::INT216:
case Type::INT224:
case Type::INT232:
case Type::INT240:
case Type::INT248:
case Type::INT256:
{
IntegerType::Bits b = static_cast<IntegerType::Bits>(
state->uRandDist->distributionOneToN(
static_cast<size_t>(IntegerType::Bits::B256)
)
);
return make_shared<IntegerType>(b, true);
} }
case Type::BOOL: case Type::BOOL:
return make_shared<BoolType>(); return make_shared<BoolType>();
case Type::FIXEDBYTES: case Type::FIXEDBYTES1:
case Type::FIXEDBYTES2:
case Type::FIXEDBYTES3:
case Type::FIXEDBYTES4:
case Type::FIXEDBYTES5:
case Type::FIXEDBYTES6:
case Type::FIXEDBYTES7:
case Type::FIXEDBYTES8:
case Type::FIXEDBYTES9:
case Type::FIXEDBYTES10:
case Type::FIXEDBYTES11:
case Type::FIXEDBYTES12:
case Type::FIXEDBYTES13:
case Type::FIXEDBYTES14:
case Type::FIXEDBYTES15:
case Type::FIXEDBYTES16:
case Type::FIXEDBYTES17:
case Type::FIXEDBYTES18:
case Type::FIXEDBYTES19:
case Type::FIXEDBYTES20:
case Type::FIXEDBYTES21:
case Type::FIXEDBYTES22:
case Type::FIXEDBYTES23:
case Type::FIXEDBYTES24:
case Type::FIXEDBYTES25:
case Type::FIXEDBYTES26:
case Type::FIXEDBYTES27:
case Type::FIXEDBYTES28:
case Type::FIXEDBYTES29:
case Type::FIXEDBYTES30:
case Type::FIXEDBYTES31:
case Type::FIXEDBYTES32:
{ {
FixedBytesType::Bytes w = static_cast<FixedBytesType::Bytes>( FixedBytesType::Bytes w = static_cast<FixedBytesType::Bytes>(
state->uRandDist->distributionOneToN( state->uRandDist->distributionOneToN(
@ -1651,11 +1853,11 @@ string FunctionCallGenerator::visit()
string MagicStmtGenerator::visit() string MagicStmtGenerator::visit()
{ {
MagicId m = static_cast<MagicId>(uRandDist()->distributionOneToN(static_cast<size_t>(MagicId::MAGICMAX) - 1)); MagicId m = static_cast<MagicId>(uRandDist()->distributionOneToN(static_cast<size_t>(MagicId::MAGICMAX) - 1));
ExpressionGenerator exprGen{state};
switch (m) switch (m)
{ {
case MagicId::ASSERT: case MagicId::ASSERT:
{ {
ExpressionGenerator exprGen{state};
auto boolType = make_shared<BoolType>(); auto boolType = make_shared<BoolType>();
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}}; pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
auto expression = exprGen.rLValueOrLiteral(boolTypeName); auto expression = exprGen.rLValueOrLiteral(boolTypeName);
@ -1668,7 +1870,6 @@ string MagicStmtGenerator::visit()
} }
case MagicId::REQUIRE: case MagicId::REQUIRE:
{ {
ExpressionGenerator exprGen{state};
auto boolType = make_shared<BoolType>(); auto boolType = make_shared<BoolType>();
pair<SolidityTypePtr, string> boolTypeName = {boolType, {}}; pair<SolidityTypePtr, string> boolTypeName = {boolType, {}};
auto expression = exprGen.rLValueOrLiteral(boolTypeName); auto expression = exprGen.rLValueOrLiteral(boolTypeName);

View File

@ -721,9 +721,103 @@ struct TypeProvider
enum class Type: size_t enum class Type: size_t
{ {
INTEGER = 1, UINT8 = 1,
UINT16,
UINT24,
UINT32,
UINT40,
UINT48,
UINT56,
UINT64,
UINT72,
UINT80,
UINT88,
UINT96,
UINT104,
UINT112,
UINT120,
UINT128,
UINT136,
UINT144,
UINT152,
UINT160,
UINT168,
UINT176,
UINT184,
UINT192,
UINT200,
UINT208,
UINT216,
UINT224,
UINT232,
UINT240,
UINT248,
UINT256,
INT8,
INT16,
INT24,
INT32,
INT40,
INT48,
INT56,
INT64,
INT72,
INT80,
INT88,
INT96,
INT104,
INT112,
INT120,
INT128,
INT136,
INT144,
INT152,
INT160,
INT168,
INT176,
INT184,
INT192,
INT200,
INT208,
INT216,
INT224,
INT232,
INT240,
INT248,
INT256,
BOOL, BOOL,
FIXEDBYTES, FIXEDBYTES1,
FIXEDBYTES2,
FIXEDBYTES3,
FIXEDBYTES4,
FIXEDBYTES5,
FIXEDBYTES6,
FIXEDBYTES7,
FIXEDBYTES8,
FIXEDBYTES9,
FIXEDBYTES10,
FIXEDBYTES11,
FIXEDBYTES12,
FIXEDBYTES13,
FIXEDBYTES14,
FIXEDBYTES15,
FIXEDBYTES16,
FIXEDBYTES17,
FIXEDBYTES18,
FIXEDBYTES19,
FIXEDBYTES20,
FIXEDBYTES21,
FIXEDBYTES22,
FIXEDBYTES23,
FIXEDBYTES24,
FIXEDBYTES25,
FIXEDBYTES26,
FIXEDBYTES27,
FIXEDBYTES28,
FIXEDBYTES29,
FIXEDBYTES30,
FIXEDBYTES31,
FIXEDBYTES32,
BYTES, BYTES,
ADDRESS, ADDRESS,
FUNCTION, FUNCTION,
@ -812,6 +906,7 @@ struct ExpressionGenerator
OR, OR,
LIT, LIT,
MEMBERACCESS, MEMBERACCESS,
MAGICEXPR,
RLMAX RLMAX
}; };
@ -843,10 +938,9 @@ struct ExpressionGenerator
std::optional<std::pair<SolidityTypePtr, std::string>> rLValueOrLiteral( std::optional<std::pair<SolidityTypePtr, std::string>> rLValueOrLiteral(
std::pair<SolidityTypePtr, std::string>& _typeName std::pair<SolidityTypePtr, std::string>& _typeName
); );
std::optional<std::pair<SolidityTypePtr, std::string>> memberAccessExpr( std::pair<SolidityTypePtr, std::string> memberAccessExpr(SolidityTypePtr& _typeName);
std::pair<SolidityTypePtr, std::string>& _typeName
);
RLValueExpr expressionType(SolidityTypePtr& _typePtr); RLValueExpr expressionType(SolidityTypePtr& _typePtr);
std::pair<SolidityTypePtr, std::string> magicExpr(SolidityTypePtr& _type);
void incrementNestingDepth() void incrementNestingDepth()
{ {