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 <libdevcore/StringUtils.h> | ||||
| #include <libdevcore/Whiskers.h> | ||||
| 
 | ||||
| #include <boost/algorithm/cxx11/all_of.hpp> | ||||
| #include <boost/algorithm/string/classification.hpp> | ||||
| @ -1385,6 +1384,14 @@ void ProtoConverter::visit(PopStmt const& _x) | ||||
| 	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) | ||||
| { | ||||
| 	m_output << "code {\n"; | ||||
| @ -1394,7 +1401,8 @@ void ProtoConverter::visit(Code 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) | ||||
| @ -1406,11 +1414,33 @@ void ProtoConverter::visit(Object const& _x) | ||||
| 	visit(_x.code()); | ||||
| 	if (_x.has_data()) | ||||
| 		visit(_x.data()); | ||||
| 	if (_x.has_obj()) | ||||
| 		visit(_x.obj()); | ||||
| 	if (_x.has_sub_obj()) | ||||
| 		visit(_x.sub_obj()); | ||||
| 	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) | ||||
| { | ||||
| 	// Initialize input size
 | ||||
| @ -1427,6 +1457,9 @@ void ProtoConverter::visit(Program const& _x) | ||||
| 		break; | ||||
| 	case Program::kObj: | ||||
| 		m_isObject = true; | ||||
| 		buildObjectScopeTree(_x.obj()); | ||||
| 		// Reset object id counter
 | ||||
| 		m_objectId = 0; | ||||
| 		visit(_x.obj()); | ||||
| 		break; | ||||
| 	case Program::PROGRAM_ONEOF_NOT_SET: | ||||
|  | ||||
| @ -26,8 +26,10 @@ | ||||
| #include <tuple> | ||||
| 
 | ||||
| #include <test/tools/ossfuzz/yulProto.pb.h> | ||||
| 
 | ||||
| #include <libdevcore/Common.h> | ||||
| #include <libdevcore/FixedHash.h> | ||||
| #include <libdevcore/Whiskers.h> | ||||
| 
 | ||||
| namespace yul | ||||
| { | ||||
| @ -240,6 +242,11 @@ private: | ||||
| 	/// Removes entry from m_functionMap and m_functionName
 | ||||
| 	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.
 | ||||
| 	/// @param _p Enum that decides if the returned token is hex prefixed ("0x") or not
 | ||||
| 	/// @return Dictionary token at the index computed using a
 | ||||
| @ -263,23 +270,28 @@ private: | ||||
| 		return "foo_" + functionTypeToString(_type) + "_" + std::to_string(counter()); | ||||
| 	} | ||||
| 
 | ||||
| 	/// Returns current object identifier as string. Input parameter
 | ||||
| 	/// is ignored.
 | ||||
| 	std::string getObjectIdentifier(ObjectId const&) | ||||
| 	{ | ||||
| 		// 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); | ||||
| 	} | ||||
| 	/// Returns a pseudo-randomly chosen object identifier that is in the
 | ||||
| 	/// scope of the Yul object being visited.
 | ||||
| 	std::string getObjectIdentifier(ObjectId const& _x); | ||||
| 
 | ||||
| 	/// Return new object identifier as string. Identifier string
 | ||||
| 	/// is a template of the form "\"object<n>\"" where <n> is
 | ||||
| 	/// 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; | ||||
| @ -297,9 +309,13 @@ private: | ||||
| 	std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope; | ||||
| 	// 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; | ||||
| 	/// 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.
 | ||||
| 	static unsigned constexpr s_modInputParams = 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
 | ||||
| 	/// statements can not be created.
 | ||||
| 	bool m_inForBodyScope; | ||||
|  | ||||
| @ -207,9 +207,9 @@ message ExtCodeCopy { | ||||
|   required Expression size = 4; | ||||
| } | ||||
| 
 | ||||
| /// TODO: Add a field that may be used for referencing | ||||
| /// a pseudo random object identifier at run time. | ||||
| message ObjectId {} | ||||
| message ObjectId { | ||||
|   required uint64 id = 1; | ||||
| } | ||||
| 
 | ||||
| message DataSize { | ||||
|   required ObjectId identifier = 1; | ||||
| @ -388,7 +388,7 @@ message Block { | ||||
| message Object { | ||||
|   required Code code = 1; | ||||
|   optional Data data = 2; | ||||
|   optional Object obj = 3; | ||||
|   optional Object sub_obj = 3; | ||||
| } | ||||
| 
 | ||||
| message Code { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user