mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10561 from ethereum/abiv2-isabelle-values
Abiv2 fuzzer: Make integer value generation consistent with range for…
This commit is contained in:
commit
fe79a27a0a
@ -1,10 +1,98 @@
|
|||||||
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
#include <test/tools/ossfuzz/protoToAbiV2.h>
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
/// Convenience macros
|
||||||
|
/// Returns a valid Solidity integer width w such that 8 <= w <= 256.
|
||||||
|
#define INTWIDTH(z, n, _ununsed) BOOST_PP_MUL(BOOST_PP_ADD(n, 1), 8)
|
||||||
|
/// Using declaration that aliases long boost multiprecision types with
|
||||||
|
/// s(u)<width> where <width> is a valid Solidity integer width and "s"
|
||||||
|
/// stands for "signed" and "u" for "unsigned".
|
||||||
|
#define USINGDECL(z, n, sign) \
|
||||||
|
using BOOST_PP_CAT(BOOST_PP_IF(sign, s, u), INTWIDTH(z, n,)) = \
|
||||||
|
boost::multiprecision::number< \
|
||||||
|
boost::multiprecision::cpp_int_backend< \
|
||||||
|
INTWIDTH(z, n,), \
|
||||||
|
INTWIDTH(z, n,), \
|
||||||
|
BOOST_PP_IF( \
|
||||||
|
sign, \
|
||||||
|
boost::multiprecision::signed_magnitude, \
|
||||||
|
boost::multiprecision::unsigned_magnitude \
|
||||||
|
), \
|
||||||
|
boost::multiprecision::unchecked, \
|
||||||
|
void \
|
||||||
|
> \
|
||||||
|
>;
|
||||||
|
/// Instantiate the using declarations for signed and unsigned integer types.
|
||||||
|
BOOST_PP_REPEAT(32, USINGDECL, 1)
|
||||||
|
BOOST_PP_REPEAT(32, USINGDECL, 0)
|
||||||
|
/// Case implementation that returns an integer value of the specified type.
|
||||||
|
/// For signed integers, we divide by two because the range for boost multiprecision
|
||||||
|
/// types is double that of Solidity integer types. Example, 8-bit signed boost
|
||||||
|
/// number range is [-255, 255] but Solidity `int8` range is [-128, 127]
|
||||||
|
#define CASEIMPL(z, n, sign) \
|
||||||
|
case INTWIDTH(z, n,): \
|
||||||
|
stream << BOOST_PP_IF( \
|
||||||
|
sign, \
|
||||||
|
integerValue< \
|
||||||
|
BOOST_PP_CAT( \
|
||||||
|
BOOST_PP_IF(sign, s, u), \
|
||||||
|
INTWIDTH(z, n,) \
|
||||||
|
)>(_counter) / 2, \
|
||||||
|
integerValue< \
|
||||||
|
BOOST_PP_CAT( \
|
||||||
|
BOOST_PP_IF(sign, s, u), \
|
||||||
|
INTWIDTH(z, n,) \
|
||||||
|
)>(_counter) \
|
||||||
|
); \
|
||||||
|
break;
|
||||||
|
/// Switch implementation that instantiates case statements for (un)signed
|
||||||
|
/// Solidity integer types.
|
||||||
|
#define SWITCHIMPL(sign) \
|
||||||
|
ostringstream stream; \
|
||||||
|
switch (_intWidth) \
|
||||||
|
{ \
|
||||||
|
BOOST_PP_REPEAT(32, CASEIMPL, sign) \
|
||||||
|
} \
|
||||||
|
return stream.str();
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::test::abiv2fuzzer;
|
using namespace solidity::test::abiv2fuzzer;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename V>
|
||||||
|
static V integerValue(unsigned _counter)
|
||||||
|
{
|
||||||
|
V value = V(
|
||||||
|
u256(solidity::util::keccak256(solidity::util::h256(_counter))) % u256(boost::math::tools::max_value<V>())
|
||||||
|
);
|
||||||
|
if (value % 2 == 0)
|
||||||
|
return value * (-1);
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string signedIntegerValue(unsigned _counter, unsigned _intWidth)
|
||||||
|
{
|
||||||
|
SWITCHIMPL(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static string unsignedIntegerValue(unsigned _counter, unsigned _intWidth)
|
||||||
|
{
|
||||||
|
SWITCHIMPL(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
static string integerValue(unsigned _counter, unsigned _intWidth, bool _signed)
|
||||||
|
{
|
||||||
|
if (_signed)
|
||||||
|
return signedIntegerValue(_counter, _intWidth);
|
||||||
|
else
|
||||||
|
return unsignedIntegerValue(_counter, _intWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string ProtoConverter::getVarDecl(
|
string ProtoConverter::getVarDecl(
|
||||||
string const& _type,
|
string const& _type,
|
||||||
string const& _varName,
|
string const& _varName,
|
||||||
@ -1013,11 +1101,7 @@ string ValueGetterVisitor::visit(BoolType const&)
|
|||||||
|
|
||||||
string ValueGetterVisitor::visit(IntegerType const& _type)
|
string ValueGetterVisitor::visit(IntegerType const& _type)
|
||||||
{
|
{
|
||||||
return integerValueAsString(
|
return integerValue(counter(), getIntWidth(_type), _type.is_signed());
|
||||||
_type.is_signed(),
|
|
||||||
getIntWidth(_type),
|
|
||||||
counter()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string ValueGetterVisitor::visit(FixedByteType const& _type)
|
string ValueGetterVisitor::visit(FixedByteType const& _type)
|
||||||
@ -1041,48 +1125,6 @@ string ValueGetterVisitor::visit(DynamicByteArrayType const& _type)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueGetterVisitor::integerValueAsString(bool _sign, unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
if (_sign)
|
|
||||||
return intValueAsString(_width, _counter);
|
|
||||||
else
|
|
||||||
return uintValueAsString(_width, _counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input(s)
|
|
||||||
* - Unsigned integer to be hashed
|
|
||||||
* - Width of desired uint value
|
|
||||||
* Processing
|
|
||||||
* - Take hash of first parameter and mask it with the max unsigned value for given bit width
|
|
||||||
* Output
|
|
||||||
* - string representation of uint value
|
|
||||||
*/
|
|
||||||
std::string ValueGetterVisitor::uintValueAsString(unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
solAssert(
|
|
||||||
(_width % 8 == 0),
|
|
||||||
"Proto ABIv2 Fuzzer: Unsigned integer width is not a multiple of 8"
|
|
||||||
);
|
|
||||||
return maskUnsignedIntToHex(_counter, _width/4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input(s)
|
|
||||||
* - counter to be hashed to derive a value for Integer type
|
|
||||||
* - Width of desired int value
|
|
||||||
* Processing
|
|
||||||
* - Take hash of first parameter and mask it with the max signed value for given bit width
|
|
||||||
* Output
|
|
||||||
* - string representation of int value
|
|
||||||
*/
|
|
||||||
std::string ValueGetterVisitor::intValueAsString(unsigned _width, unsigned _counter)
|
|
||||||
{
|
|
||||||
solAssert(
|
|
||||||
(_width % 8 == 0),
|
|
||||||
"Proto ABIv2 Fuzzer: Signed integer width is not a multiple of 8"
|
|
||||||
);
|
|
||||||
return maskUnsignedIntToHex(_counter, ((_width/4) - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ValueGetterVisitor::croppedString(
|
std::string ValueGetterVisitor::croppedString(
|
||||||
unsigned _numBytes,
|
unsigned _numBytes,
|
||||||
unsigned _counter,
|
unsigned _counter,
|
||||||
@ -1153,9 +1195,10 @@ std::string ValueGetterVisitor::fixedByteValueAsString(unsigned _width, unsigned
|
|||||||
|
|
||||||
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
std::string ValueGetterVisitor::addressValueAsString(unsigned _counter)
|
||||||
{
|
{
|
||||||
return Whiskers(R"(address(<value>))")
|
// TODO: Isabelle encoder expects address literal to be exactly
|
||||||
("value", uintValueAsString(160, _counter))
|
// 20 bytes and a hex string.
|
||||||
.render();
|
// Example: 0x0102030405060708090a0102030405060708090a
|
||||||
|
return "address(" + maskUnsignedIntToHex(_counter, 40) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ValueGetterVisitor::variableLengthValueAsString(
|
std::string ValueGetterVisitor::variableLengthValueAsString(
|
||||||
|
@ -792,9 +792,6 @@ private:
|
|||||||
return m_counter++;
|
return m_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string intValueAsString(unsigned _width, unsigned _counter);
|
|
||||||
static std::string uintValueAsString(unsigned _width, unsigned _counter);
|
|
||||||
static std::string integerValueAsString(bool _sign, unsigned _width, unsigned _counter);
|
|
||||||
static std::string addressValueAsString(unsigned _counter);
|
static std::string addressValueAsString(unsigned _counter);
|
||||||
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user