mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Store stack height in analysis phase.
This commit is contained in:
		
							parent
							
								
									a46a059e3a
								
							
						
					
					
						commit
						68218387cf
					
				| @ -41,9 +41,10 @@ using namespace dev::solidity::assembly; | ||||
| AsmAnalyzer::AsmAnalyzer( | ||||
| 	AsmAnalyzer::Scopes& _scopes, | ||||
| 	ErrorList& _errors, | ||||
| 	ExternalIdentifierAccess::Resolver const& _resolver | ||||
| 	ExternalIdentifierAccess::Resolver const& _resolver, | ||||
| 	StackHeightInfo* _stackHeightInfo | ||||
| ): | ||||
| 	m_resolver(_resolver), m_scopes(_scopes), m_errors(_errors) | ||||
| 	m_resolver(_resolver), m_scopes(_scopes), m_errors(_errors), m_stackHeightInfo(_stackHeightInfo) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| @ -55,10 +56,16 @@ bool AsmAnalyzer::analyze(Block const& _block) | ||||
| 	return (*this)(_block); | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(const Label& _label) | ||||
| { | ||||
| 	storeStackHeight(_label); return true; | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) | ||||
| { | ||||
| 	auto const& info = instructionInfo(_instruction.instruction); | ||||
| 	m_stackHeight += info.ret - info.args; | ||||
| 	storeStackHeight(_instruction); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| @ -74,6 +81,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) | ||||
| 		)); | ||||
| 		return false; | ||||
| 	} | ||||
| 	storeStackHeight(_literal); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| @ -129,6 +137,7 @@ bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) | ||||
| 		} | ||||
| 		m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize; | ||||
| 	} | ||||
| 	storeStackHeight(_identifier); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -147,14 +156,18 @@ bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) | ||||
| 	solAssert(instructionInfo(_instr.instruction.instruction).args == int(_instr.arguments.size()), ""); | ||||
| 	if (!(*this)(_instr.instruction)) | ||||
| 		success = false; | ||||
| 	storeStackHeight(_instr); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment) | ||||
| { | ||||
| 	return checkAssignment(_assignment.variableName, size_t(-1)); | ||||
| 	bool success = checkAssignment(_assignment.variableName, size_t(-1)); | ||||
| 	storeStackHeight(_assignment); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool AsmAnalyzer::operator()(FunctionalAssignment const& _assignment) | ||||
| { | ||||
| 	int const stackHeight = m_stackHeight; | ||||
| @ -162,6 +175,7 @@ bool AsmAnalyzer::operator()(FunctionalAssignment const& _assignment) | ||||
| 	solAssert(m_stackHeight >= stackHeight, "Negative value size."); | ||||
| 	if (!checkAssignment(_assignment.variableName, m_stackHeight - stackHeight)) | ||||
| 		success = false; | ||||
| 	storeStackHeight(_assignment); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -171,6 +185,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) | ||||
| 	bool success = boost::apply_visitor(*this, *_varDecl.value); | ||||
| 	solAssert(m_stackHeight - stackHeight == 1, "Invalid value size."); | ||||
| 	boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.name)).active = true; | ||||
| 	storeStackHeight(_varDecl); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -187,6 +202,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) | ||||
| 	bool success = (*this)(_funDef.body); | ||||
| 
 | ||||
| 	m_stackHeight = stackHeight; | ||||
| 	storeStackHeight(_funDef); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -253,6 +269,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) | ||||
| 			success = false; | ||||
| 	} | ||||
| 	m_stackHeight += int(returns) - int(arguments); | ||||
| 	storeStackHeight(_funCall); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -289,6 +306,7 @@ bool AsmAnalyzer::operator()(Block const& _block) | ||||
| 	} | ||||
| 
 | ||||
| 	m_currentScope = m_currentScope->superScope; | ||||
| 	storeStackHeight(_block); | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| @ -354,6 +372,12 @@ bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t | ||||
| 	return success; | ||||
| } | ||||
| 
 | ||||
| void AsmAnalyzer::storeStackHeight(const assembly::Statement& _statement) | ||||
| { | ||||
| 	if (m_stackHeightInfo) | ||||
| 		(*m_stackHeightInfo)[&_statement] = m_stackHeight; | ||||
| } | ||||
| 
 | ||||
| bool AsmAnalyzer::expectDeposit(int const _deposit, int const _oldHeight, SourceLocation const& _location) | ||||
| { | ||||
| 	int stackDiff = m_stackHeight - _oldHeight; | ||||
|  | ||||
| @ -50,6 +50,9 @@ struct FunctionCall; | ||||
| 
 | ||||
| struct Scope; | ||||
| 
 | ||||
| using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>; | ||||
| using StackHeightInfo = std::map<assembly::Statement const*, int>; | ||||
| 
 | ||||
| /**
 | ||||
|  * Performs the full analysis stage, calls the ScopeFiller internally, then resolves | ||||
|  * references and performs other checks. | ||||
| @ -62,7 +65,8 @@ public: | ||||
| 	AsmAnalyzer( | ||||
| 		Scopes& _scopes, | ||||
| 		ErrorList& _errors, | ||||
| 		ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() | ||||
| 		ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver(), | ||||
| 		StackHeightInfo* _stackHeightInfo = nullptr | ||||
| 	); | ||||
| 
 | ||||
| 	bool analyze(assembly::Block const& _block); | ||||
| @ -71,7 +75,7 @@ public: | ||||
| 	bool operator()(assembly::Literal const& _literal); | ||||
| 	bool operator()(assembly::Identifier const&); | ||||
| 	bool operator()(assembly::FunctionalInstruction const& _functionalInstruction); | ||||
| 	bool operator()(assembly::Label const&) { return true; } | ||||
| 	bool operator()(assembly::Label const& _label); | ||||
| 	bool operator()(assembly::Assignment const&); | ||||
| 	bool operator()(assembly::FunctionalAssignment const& _functionalAssignment); | ||||
| 	bool operator()(assembly::VariableDeclaration const& _variableDeclaration); | ||||
| @ -84,6 +88,7 @@ private: | ||||
| 	/// as the value, @a _valueSize, unless that is equal to -1.
 | ||||
| 	bool checkAssignment(assembly::Identifier const& _assignment, size_t _valueSize = size_t(-1)); | ||||
| 	bool expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location); | ||||
| 	void storeStackHeight(assembly::Statement const& _statement); | ||||
| 	Scope& scope(assembly::Block const* _block); | ||||
| 
 | ||||
| 	/// This is used when we enter the body of a function definition. There, the parameters
 | ||||
| @ -95,6 +100,7 @@ private: | ||||
| 	Scope* m_currentScope = nullptr; | ||||
| 	Scopes& m_scopes; | ||||
| 	ErrorList& m_errors; | ||||
| 	StackHeightInfo* m_stackHeightInfo; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user