Experimental

This commit is contained in:
Bhargava Shastry 2019-08-02 17:01:41 +02:00
parent 12f54b55a2
commit 1735a82199
2 changed files with 50 additions and 28 deletions

View File

@ -388,11 +388,14 @@ void ProtoConverter::visit(StructType const&)
{ {
} }
std::string ProtoConverter::arrayDimInfoAsString(ArrayDimensionInfo const& _x) std::string ProtoConverter::arrayDimInfoAsString(
ArrayDimensionInfo const& _x,
unsigned _numDimensions
)
{ {
return Whiskers(R"([<?isStatic><length></isStatic>])") return Whiskers(R"([<?isStatic><length></isStatic>])")
("isStatic", _x.is_static()) ("isStatic", _x.is_static())
("length", std::to_string(getStaticArrayLengthFromFuzz(_x.length()))) ("length", std::to_string(getStaticArrayLengthFromFuzz(_x.length(), _numDimensions)))
.render(); .render();
} }
@ -402,7 +405,7 @@ void ProtoConverter::arrayDimensionsAsStringVector(
{ {
solAssert(_x.info_size() > 0, "Proto ABIv2 Fuzzer: Array dimensions empty."); solAssert(_x.info_size() > 0, "Proto ABIv2 Fuzzer: Array dimensions empty.");
for (auto const& dim: _x.info()) for (auto const& dim: _x.info())
_vecOfStr.push_back(arrayDimInfoAsString(dim)); _vecOfStr.push_back(arrayDimInfoAsString(dim, _x.info_size()));
} }
ProtoConverter::VecOfBoolUnsigned ProtoConverter::arrayDimensionsAsPairVector( ProtoConverter::VecOfBoolUnsigned ProtoConverter::arrayDimensionsAsPairVector(
@ -411,7 +414,7 @@ ProtoConverter::VecOfBoolUnsigned ProtoConverter::arrayDimensionsAsPairVector(
{ {
VecOfBoolUnsigned arrayDimsPairVector = {}; VecOfBoolUnsigned arrayDimsPairVector = {};
for (auto const& dim: _x.info()) for (auto const& dim: _x.info())
arrayDimsPairVector.push_back(arrayDimInfoAsPair(dim)); arrayDimsPairVector.push_back(arrayDimInfoAsPair(dim, _x.info_size()));
solAssert(!arrayDimsPairVector.empty(), "Proto ABIv2 Fuzzer: Array dimensions empty."); solAssert(!arrayDimsPairVector.empty(), "Proto ABIv2 Fuzzer: Array dimensions empty.");
return arrayDimsPairVector; return arrayDimsPairVector;
} }
@ -467,7 +470,8 @@ unsigned ProtoConverter::resizeDimension(
unsigned _arrayLen, unsigned _arrayLen,
std::string const& _var, std::string const& _var,
std::string const& _param, std::string const& _param,
std::string const& _type std::string const& _type,
unsigned _numDimensions
) )
{ {
unsigned length; unsigned length;
@ -475,7 +479,7 @@ unsigned ProtoConverter::resizeDimension(
length = _arrayLen; length = _arrayLen;
else else
{ {
length = getDynArrayLengthFromFuzz(_arrayLen, getNextCounter()); length = getDynArrayLengthFromFuzz(_arrayLen, getNextCounter(), _numDimensions);
// If local var, new T(l); // If local var, new T(l);
// Else, l; // Else, l;
@ -501,7 +505,7 @@ unsigned ProtoConverter::resizeDimension(
} }
// Add checks on array length pseudo randomly // Add checks on array length pseudo randomly
if (addCheck(getNextCounter())) if (addCheck(getNextCounter(), _numDimensions))
// if (c.length != l) // if (c.length != l)
checkResizeOp(_param, length); checkResizeOp(_param, length);
return length; return length;
@ -512,7 +516,8 @@ void ProtoConverter::resizeHelper(
std::vector<std::string> _arrStrVec, std::vector<std::string> _arrStrVec,
VecOfBoolUnsigned _arrInfoVec, VecOfBoolUnsigned _arrInfoVec,
std::string const& _varName, std::string const& _varName,
std::string const& _paramName std::string const& _paramName,
unsigned _numDimensions
) )
{ {
// Initialize value expressions if we have arrived at leaf node, // Initialize value expressions if we have arrived at leaf node,
@ -523,7 +528,7 @@ void ProtoConverter::resizeHelper(
// To ensure we do not create a very large test case // To ensure we do not create a very large test case
// especially for multidimensional dynamic arrays, // especially for multidimensional dynamic arrays,
// we create a checked assignment pseudo randomly. // we create a checked assignment pseudo randomly.
if (addCheck(getNextCounter())) if (addCheck(getNextCounter(), _numDimensions))
{ {
// expression name is _var // expression name is _var
// value is a value of base type // value is a value of base type
@ -542,7 +547,7 @@ void ProtoConverter::resizeHelper(
_arrStrVec.end(), _arrStrVec.end(),
std::string("") std::string("")
); );
unsigned length = resizeDimension(dim.first, dim.second, _varName, _paramName, type); unsigned length = resizeDimension(dim.first, dim.second, _varName, _paramName, type, _numDimensions);
// Recurse one level dimension down. // Recurse one level dimension down.
_arrStrVec.pop_back(); _arrStrVec.pop_back();
_arrInfoVec.pop_back(); _arrInfoVec.pop_back();
@ -552,7 +557,8 @@ void ProtoConverter::resizeHelper(
_arrStrVec, _arrStrVec,
_arrInfoVec, _arrInfoVec,
_varName + "[" + std::to_string(i) + "]", _varName + "[" + std::to_string(i) + "]",
_paramName + "[" + std::to_string(i) + "]" _paramName + "[" + std::to_string(i) + "]",
_numDimensions
); );
} }
} }
@ -569,7 +575,7 @@ void ProtoConverter::resizeInitArray(
VecOfBoolUnsigned arrInfoVec = arrayDimensionsAsPairVector(_x); VecOfBoolUnsigned arrInfoVec = arrayDimensionsAsPairVector(_x);
std::vector<std::string> arrStrVec = {_baseType}; std::vector<std::string> arrStrVec = {_baseType};
arrayDimensionsAsStringVector(_x, arrStrVec); arrayDimensionsAsStringVector(_x, arrStrVec);
resizeHelper(_x, arrStrVec, arrInfoVec, _varName, _paramName); resizeHelper(_x, arrStrVec, arrInfoVec, _varName, _paramName, arrInfoVec.size());
} }
// Returns array type from it's base type (e.g., int8) and array dimensions info contained in // Returns array type from it's base type (e.g., int8) and array dimensions info contained in

View File

@ -174,7 +174,8 @@ private:
unsigned _arrayLen, unsigned _arrayLen,
std::string const& _var, std::string const& _var,
std::string const& _param, std::string const& _param,
std::string const& _type std::string const& _type,
unsigned _numDimensions
); );
void resizeHelper( void resizeHelper(
@ -182,7 +183,8 @@ private:
std::vector<std::string> _arrStrVec, std::vector<std::string> _arrStrVec,
VecOfBoolUnsigned _arrInfoVec, VecOfBoolUnsigned _arrInfoVec,
std::string const& _varName, std::string const& _varName,
std::string const& _paramName std::string const& _paramName,
unsigned _numDimensions
); );
// Utility functions // Utility functions
@ -293,7 +295,7 @@ private:
bool _isHexLiteral bool _isHexLiteral
); );
static std::vector<std::pair<bool, unsigned>> arrayDimensionsAsPairVector(ArrayType const& _x); static std::vector<std::pair<bool, unsigned>> arrayDimensionsAsPairVector(ArrayType const& _x);
static std::string arrayDimInfoAsString(ArrayDimensionInfo const& _x); static std::string arrayDimInfoAsString(ArrayDimensionInfo const& _x, unsigned _numDimensions);
static void arrayDimensionsAsStringVector( static void arrayDimensionsAsStringVector(
ArrayType const& _x, ArrayType const& _x,
std::vector<std::string>& std::vector<std::string>&
@ -371,25 +373,40 @@ private:
/// Dynamically sized arrays can have a length of at least zero /// Dynamically sized arrays can have a length of at least zero
/// and at most s_maxArrayLength. /// and at most s_maxArrayLength.
static unsigned getDynArrayLengthFromFuzz(unsigned _fuzz, unsigned _counter) static unsigned getDynArrayLengthFromFuzz(
unsigned _fuzz,
unsigned _counter,
unsigned _numDimensions
)
{ {
// Zero length dimension is more likely when the total
// number of dimensions is high.
return (
_fuzz % _numDimensions != 0 ?
0 :
// Increment modulo value by one in order to meet upper bound // Increment modulo value by one in order to meet upper bound
return (_fuzz + _counter) % (s_maxArrayLength + 1); (_fuzz + _counter) % (s_maxArrayLength + 1)
);
} }
/// Statically sized arrays must have a length of at least one /// Statically sized arrays must have a length of at least one
/// and at most s_maxArrayLength. /// and at most s_maxArrayLength.
static unsigned getStaticArrayLengthFromFuzz(unsigned _fuzz) static unsigned getStaticArrayLengthFromFuzz(unsigned _fuzz, unsigned _numDimensions)
{ {
return _fuzz % s_maxArrayLength + 1; // Unit length dimension is more likely when the total
// number of dimensions is high.
return (_fuzz % _numDimensions != 0 ? 1 : _fuzz % s_maxArrayLength + 1);
} }
static std::pair<bool, unsigned> arrayDimInfoAsPair(ArrayDimensionInfo const& _x) static std::pair<bool, unsigned> arrayDimInfoAsPair(
ArrayDimensionInfo const& _x,
unsigned _numDimensions
)
{ {
return ( return (
_x.is_static() ? _x.is_static() ?
std::make_pair(true, getStaticArrayLengthFromFuzz(_x.length())) : std::make_pair(true, getStaticArrayLengthFromFuzz(_x.length(), _numDimensions)) :
std::make_pair(false, getDynArrayLengthFromFuzz(_x.length(), 0)) std::make_pair(false, getDynArrayLengthFromFuzz(_x.length(), 0, _numDimensions))
); );
} }
@ -413,10 +430,12 @@ private:
_counter, _counter,
_isHexLiteral _isHexLiteral
); );
}
static bool addCheck(unsigned _counter) /// Checks are less likely for higher dimensional arrays
static bool addCheck(unsigned _counter, unsigned _numDimensions)
{ {
return _counter % s_arrayCheckFrequency == 0; return _counter % _numDimensions == 0;
} }
/// Contains the test program /// Contains the test program
@ -438,9 +457,6 @@ private:
static unsigned constexpr s_maxArrayLength = 4; static unsigned constexpr s_maxArrayLength = 4;
static unsigned constexpr s_maxArrayDimensions = 4; static unsigned constexpr s_maxArrayDimensions = 4;
static unsigned constexpr s_maxDynArrayLength = 256; static unsigned constexpr s_maxDynArrayLength = 256;
/// Add check only if counter returned by getNextCounter()
/// is divisible by s_arrayCheckFrequency
static unsigned constexpr s_arrayCheckFrequency = 11;
/// Prefixes for declared and parameterized variable names /// Prefixes for declared and parameterized variable names
static auto constexpr s_varNamePrefix = "x_"; static auto constexpr s_varNamePrefix = "x_";
static auto constexpr s_paramNamePrefix = "c_"; static auto constexpr s_paramNamePrefix = "c_";