mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Pseudo-randomly choose object/data identifier that is in scope
This commit is contained in:
parent
d677a15507
commit
34022a2c8c
@ -21,7 +21,6 @@
|
|||||||
#include <libyul/Exceptions.h>
|
#include <libyul/Exceptions.h>
|
||||||
|
|
||||||
#include <libdevcore/StringUtils.h>
|
#include <libdevcore/StringUtils.h>
|
||||||
#include <libdevcore/Whiskers.h>
|
|
||||||
|
|
||||||
#include <boost/algorithm/cxx11/all_of.hpp>
|
#include <boost/algorithm/cxx11/all_of.hpp>
|
||||||
#include <boost/algorithm/string/classification.hpp>
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
@ -1385,6 +1384,14 @@ void ProtoConverter::visit(PopStmt const& _x)
|
|||||||
m_output << ")\n";
|
m_output << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ProtoConverter::getObjectIdentifier(ObjectId const& _x)
|
||||||
|
{
|
||||||
|
unsigned currentId = currentObjectId();
|
||||||
|
yulAssert(m_objectScopeTree.size() > currentId, "Proto fuzzer: Error referencing object");
|
||||||
|
std::vector<std::string> objectIdsInScope = m_objectScopeTree[currentId];
|
||||||
|
return objectIdsInScope[_x.id() % objectIdsInScope.size()];
|
||||||
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(Code const& _x)
|
void ProtoConverter::visit(Code const& _x)
|
||||||
{
|
{
|
||||||
m_output << "code {\n";
|
m_output << "code {\n";
|
||||||
@ -1394,7 +1401,8 @@ void ProtoConverter::visit(Code const& _x)
|
|||||||
|
|
||||||
void ProtoConverter::visit(Data const& _x)
|
void ProtoConverter::visit(Data const& _x)
|
||||||
{
|
{
|
||||||
m_output << "data \"datablock\" hex\"" << createHex(_x.hex()) << "\"\n";
|
// TODO: Generate random data block identifier
|
||||||
|
m_output << "data \"" << s_dataIdentifier << "\" hex\"" << createHex(_x.hex()) << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(Object const& _x)
|
void ProtoConverter::visit(Object const& _x)
|
||||||
@ -1406,11 +1414,33 @@ void ProtoConverter::visit(Object const& _x)
|
|||||||
visit(_x.code());
|
visit(_x.code());
|
||||||
if (_x.has_data())
|
if (_x.has_data())
|
||||||
visit(_x.data());
|
visit(_x.data());
|
||||||
if (_x.has_obj())
|
if (_x.has_sub_obj())
|
||||||
visit(_x.obj());
|
visit(_x.sub_obj());
|
||||||
m_output << "}\n";
|
m_output << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProtoConverter::buildObjectScopeTree(Object const& _x)
|
||||||
|
{
|
||||||
|
// Identifies object being visited
|
||||||
|
string objectId = newObjectId(false);
|
||||||
|
vector<string> node{objectId};
|
||||||
|
if (_x.has_data())
|
||||||
|
node.push_back(s_dataIdentifier);
|
||||||
|
if (_x.has_sub_obj())
|
||||||
|
{
|
||||||
|
// Identifies sub object whose numeric suffix is
|
||||||
|
// m_objectId
|
||||||
|
string subObjectId = "object" + to_string(m_objectId);
|
||||||
|
node.push_back(subObjectId);
|
||||||
|
// TODO: Add sub-object to object's ancestors once
|
||||||
|
// nested access is implemented.
|
||||||
|
m_objectScopeTree.push_back(node);
|
||||||
|
buildObjectScopeTree(_x.sub_obj());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_objectScopeTree.push_back(node);
|
||||||
|
}
|
||||||
|
|
||||||
void ProtoConverter::visit(Program const& _x)
|
void ProtoConverter::visit(Program const& _x)
|
||||||
{
|
{
|
||||||
// Initialize input size
|
// Initialize input size
|
||||||
@ -1427,6 +1457,9 @@ void ProtoConverter::visit(Program const& _x)
|
|||||||
break;
|
break;
|
||||||
case Program::kObj:
|
case Program::kObj:
|
||||||
m_isObject = true;
|
m_isObject = true;
|
||||||
|
buildObjectScopeTree(_x.obj());
|
||||||
|
// Reset object id counter
|
||||||
|
m_objectId = 0;
|
||||||
visit(_x.obj());
|
visit(_x.obj());
|
||||||
break;
|
break;
|
||||||
case Program::PROGRAM_ONEOF_NOT_SET:
|
case Program::PROGRAM_ONEOF_NOT_SET:
|
||||||
|
@ -26,8 +26,10 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||||
|
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
#include <libdevcore/FixedHash.h>
|
#include <libdevcore/FixedHash.h>
|
||||||
|
#include <libdevcore/Whiskers.h>
|
||||||
|
|
||||||
namespace yul
|
namespace yul
|
||||||
{
|
{
|
||||||
@ -240,6 +242,11 @@ private:
|
|||||||
/// Removes entry from m_functionMap and m_functionName
|
/// Removes entry from m_functionMap and m_functionName
|
||||||
void updateFunctionMaps(std::string const& _x);
|
void updateFunctionMaps(std::string const& _x);
|
||||||
|
|
||||||
|
/// Build a tree of objects that contains the object/data
|
||||||
|
/// identifiers that are in scope in a given object.
|
||||||
|
/// @param _x root object of the yul protobuf specification.
|
||||||
|
void buildObjectScopeTree(Object const& _x);
|
||||||
|
|
||||||
/// Returns a pseudo-random dictionary token.
|
/// Returns a pseudo-random dictionary token.
|
||||||
/// @param _p Enum that decides if the returned token is hex prefixed ("0x") or not
|
/// @param _p Enum that decides if the returned token is hex prefixed ("0x") or not
|
||||||
/// @return Dictionary token at the index computed using a
|
/// @return Dictionary token at the index computed using a
|
||||||
@ -263,23 +270,28 @@ private:
|
|||||||
return "foo_" + functionTypeToString(_type) + "_" + std::to_string(counter());
|
return "foo_" + functionTypeToString(_type) + "_" + std::to_string(counter());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns current object identifier as string. Input parameter
|
/// Returns a pseudo-randomly chosen object identifier that is in the
|
||||||
/// is ignored.
|
/// scope of the Yul object being visited.
|
||||||
std::string getObjectIdentifier(ObjectId const&)
|
std::string getObjectIdentifier(ObjectId const& _x);
|
||||||
{
|
|
||||||
// TODO: Return a pseudo randomly chosen object identifier
|
|
||||||
// that is in scope as string.
|
|
||||||
// At the moment, we simply return the identifier that
|
|
||||||
// corresponds to the currently visited object.
|
|
||||||
return "object" + std::to_string(m_objectId - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return new object identifier as string. Identifier string
|
/// Return new object identifier as string. Identifier string
|
||||||
/// is a template of the form "\"object<n>\"" where <n> is
|
/// is a template of the form "\"object<n>\"" where <n> is
|
||||||
/// a monotonically increasing object ID counter.
|
/// a monotonically increasing object ID counter.
|
||||||
std::string newObjectId()
|
/// @param _decorate If true (default value), object ID is
|
||||||
|
/// enclosed within double quotes.
|
||||||
|
std::string newObjectId(bool _decorate = true)
|
||||||
{
|
{
|
||||||
return "\"object" + std::to_string(m_objectId++) + "\"";
|
return dev::Whiskers(R"(<?decorate>"</decorate>object<id><?decorate>"</decorate>)")
|
||||||
|
("decorate", _decorate)
|
||||||
|
("id", std::to_string(m_objectId++))
|
||||||
|
.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the object counter value corresponding to the object
|
||||||
|
/// being visited.
|
||||||
|
unsigned currentObjectId()
|
||||||
|
{
|
||||||
|
return m_objectId - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream m_output;
|
std::ostringstream m_output;
|
||||||
@ -297,9 +309,13 @@ private:
|
|||||||
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
|
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
|
||||||
// Look-up table per function type that holds the number of input (output) function parameters
|
// Look-up table per function type that holds the number of input (output) function parameters
|
||||||
std::map<std::string, std::pair<unsigned, unsigned>> m_functionSigMap;
|
std::map<std::string, std::pair<unsigned, unsigned>> m_functionSigMap;
|
||||||
|
/// Tree of objects and their scopes
|
||||||
|
std::vector<std::vector<std::string>> m_objectScopeTree;
|
||||||
// mod input/output parameters impose an upper bound on the number of input/output parameters a function may have.
|
// mod input/output parameters impose an upper bound on the number of input/output parameters a function may have.
|
||||||
static unsigned constexpr s_modInputParams = 5;
|
static unsigned constexpr s_modInputParams = 5;
|
||||||
static unsigned constexpr s_modOutputParams = 5;
|
static unsigned constexpr s_modOutputParams = 5;
|
||||||
|
/// Hard-coded identifier for a Yul object's data block
|
||||||
|
static auto constexpr s_dataIdentifier = "datablock";
|
||||||
/// Predicate to keep track of for body scope. If true, break/continue
|
/// Predicate to keep track of for body scope. If true, break/continue
|
||||||
/// statements can not be created.
|
/// statements can not be created.
|
||||||
bool m_inForBodyScope;
|
bool m_inForBodyScope;
|
||||||
|
@ -207,9 +207,9 @@ message ExtCodeCopy {
|
|||||||
required Expression size = 4;
|
required Expression size = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: Add a field that may be used for referencing
|
message ObjectId {
|
||||||
/// a pseudo random object identifier at run time.
|
required uint64 id = 1;
|
||||||
message ObjectId {}
|
}
|
||||||
|
|
||||||
message DataSize {
|
message DataSize {
|
||||||
required ObjectId identifier = 1;
|
required ObjectId identifier = 1;
|
||||||
@ -388,7 +388,7 @@ message Block {
|
|||||||
message Object {
|
message Object {
|
||||||
required Code code = 1;
|
required Code code = 1;
|
||||||
optional Data data = 2;
|
optional Data data = 2;
|
||||||
optional Object obj = 3;
|
optional Object sub_obj = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Code {
|
message Code {
|
||||||
|
Loading…
Reference in New Issue
Block a user