diff options
author | chriseth <chris@ethereum.org> | 2017-04-26 22:50:54 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2017-04-26 23:12:04 +0800 |
commit | d7b3ce24a4f26a7bd81f3beade1042ae33974584 (patch) | |
tree | 3be103a452e0238a26c1b05fb3d1dd8e47275141 | |
parent | f3ec2ba39e7f4b85d148a7b696ef5af499fbb6fb (diff) | |
download | dexon-solidity-d7b3ce24a4f26a7bd81f3beade1042ae33974584.tar.gz dexon-solidity-d7b3ce24a4f26a7bd81f3beade1042ae33974584.tar.zst dexon-solidity-d7b3ce24a4f26a7bd81f3beade1042ae33974584.zip |
Check stack height during code generation.
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index be52db46..9ef3e6e7 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -78,12 +78,23 @@ public: GeneratorState& _state, assembly::Block const& _block, assembly::ExternalIdentifierAccess const& _identifierAccess = assembly::ExternalIdentifierAccess() + ): CodeTransform(_state, _block, _identifierAccess, _state.assembly.deposit()) + { + } + +private: + CodeTransform( + GeneratorState& _state, + assembly::Block const& _block, + assembly::ExternalIdentifierAccess const& _identifierAccess, + int _initialDeposit ): m_state(_state), m_scope(*m_state.info.scopes.at(&_block)), - m_initialDeposit(m_state.assembly.deposit()), - m_identifierAccess(_identifierAccess) + m_identifierAccess(_identifierAccess), + m_initialDeposit(_initialDeposit) { + int blockStartDeposit = m_state.assembly.deposit(); std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); m_state.assembly.setSourceLocation(_block.location); @@ -93,15 +104,16 @@ public: if (identifier.second.type() == typeid(Scope::Variable)) m_state.assembly.append(solidity::Instruction::POP); - int deposit = m_state.assembly.deposit() - m_initialDeposit; - + int deposit = m_state.assembly.deposit() - blockStartDeposit; solAssert(deposit == 0, "Invalid stack height at end of block."); } +public: void operator()(assembly::Instruction const& _instruction) { m_state.assembly.setSourceLocation(_instruction.location); m_state.assembly.append(_instruction.instruction); + checkStackHeight(&_instruction); } void operator()(assembly::Literal const& _literal) { @@ -113,6 +125,7 @@ public: solAssert(_literal.value.size() <= 32, ""); m_state.assembly.append(u256(h256(_literal.value, h256::FromBinary, h256::AlignLeft))); } + checkStackHeight(&_literal); } void operator()(assembly::Identifier const& _identifier) { @@ -145,6 +158,7 @@ public: "Identifier not found and no external access available." ); m_identifierAccess.generateCode(_identifier, IdentifierContext::RValue, m_state.assembly); + checkStackHeight(&_identifier); } void operator()(FunctionalInstruction const& _instr) { @@ -155,6 +169,7 @@ public: expectDeposit(1, height); } (*this)(_instr.instruction); + checkStackHeight(&_instr); } void operator()(assembly::FunctionCall const&) { @@ -167,11 +182,13 @@ public: Scope::Label& label = boost::get<Scope::Label>(m_scope.identifiers.at(_label.name)); assignLabelIdIfUnset(label); m_state.assembly.append(eth::AssemblyItem(eth::Tag, label.id)); + checkStackHeight(&_label); } void operator()(assembly::Assignment const& _assignment) { m_state.assembly.setSourceLocation(_assignment.location); generateAssignment(_assignment.variableName, _assignment.location); + checkStackHeight(&_assignment); } void operator()(FunctionalAssignment const& _assignment) { @@ -180,6 +197,7 @@ public: expectDeposit(1, height); m_state.assembly.setSourceLocation(_assignment.location); generateAssignment(_assignment.variableName, _assignment.location); + checkStackHeight(&_assignment); } void operator()(assembly::VariableDeclaration const& _varDecl) { @@ -192,7 +210,8 @@ public: } void operator()(assembly::Block const& _block) { - CodeTransform(m_state, _block, m_identifierAccess); + CodeTransform(m_state, _block, m_identifierAccess, m_initialDeposit); + checkStackHeight(&_block); } void operator()(assembly::FunctionDefinition const&) { @@ -245,6 +264,15 @@ private: solAssert(m_state.assembly.deposit() == _oldHeight + _deposit, "Invalid stack deposit."); } + void checkStackHeight(void const* _astElement) + { + solAssert(m_state.info.stackHeightInfo.count(_astElement), "Stack height for AST element not found."); + solAssert( + m_state.info.stackHeightInfo.at(_astElement) == m_state.assembly.deposit() - m_initialDeposit, + "Stack height mismatch between analysis and code generation phase." + ); + } + /// Assigns the label's id to a value taken from eth::Assembly if it has not yet been set. void assignLabelIdIfUnset(Scope::Label& _label) { @@ -257,8 +285,8 @@ private: GeneratorState& m_state; Scope& m_scope; - int const m_initialDeposit; ExternalIdentifierAccess m_identifierAccess; + int const m_initialDeposit; }; eth::Assembly assembly::CodeGenerator::assemble( |