diff --git a/Compiler.cpp b/Compiler.cpp index 23014da6c..e691394cb 100644 --- a/Compiler.cpp +++ b/Compiler.cpp @@ -34,6 +34,20 @@ using namespace std; namespace dev { namespace solidity { +/** + * Simple helper class to ensure that the stack height is the same at certain places in the code. + */ +class StackHeightChecker +{ +public: + StackHeightChecker(CompilerContext const& _context): + m_context(_context), stackHeight(m_context.getStackHeight()) {} + void check() { solAssert(m_context.getStackHeight() == stackHeight, "I sense a disturbance in the stack."); } +private: + CompilerContext const& m_context; + unsigned stackHeight; +}; + void Compiler::compileContract(ContractDefinition const& _contract, map const& _contracts) { @@ -340,6 +354,8 @@ bool Compiler::visit(FunctionDefinition const& _function) bool Compiler::visit(IfStatement const& _ifStatement) { + StackHeightChecker checker(m_context); + compileExpression(_ifStatement.getCondition()); eth::AssemblyItem trueTag = m_context.appendConditionalJump(); if (_ifStatement.getFalseStatement()) @@ -348,11 +364,15 @@ bool Compiler::visit(IfStatement const& _ifStatement) m_context << trueTag; _ifStatement.getTrueStatement().accept(*this); m_context << endTag; + + checker.check(); return false; } bool Compiler::visit(WhileStatement const& _whileStatement) { + StackHeightChecker checker(m_context); + eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag(); m_continueTags.push_back(loopStart); @@ -370,11 +390,15 @@ bool Compiler::visit(WhileStatement const& _whileStatement) m_continueTags.pop_back(); m_breakTags.pop_back(); + + checker.check(); return false; } bool Compiler::visit(ForStatement const& _forStatement) { + StackHeightChecker checker(m_context); + eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag(); m_continueTags.push_back(loopStart); @@ -404,6 +428,8 @@ bool Compiler::visit(ForStatement const& _forStatement) m_continueTags.pop_back(); m_breakTags.pop_back(); + + checker.check(); return false; } @@ -438,29 +464,35 @@ bool Compiler::visit(Return const& _return) return false; } -bool Compiler::visit(VariableDeclarationStatement const& _variableDefinition) +bool Compiler::visit(VariableDeclarationStatement const& _variableDeclarationStatement) { - if (Expression const* expression = _variableDefinition.getExpression()) + StackHeightChecker checker(m_context); + if (Expression const* expression = _variableDeclarationStatement.getExpression()) { - compileExpression(*expression, _variableDefinition.getDeclaration().getType()); - CompilerUtils(m_context).moveToStackVariable(_variableDefinition.getDeclaration()); + compileExpression(*expression, _variableDeclarationStatement.getDeclaration().getType()); + CompilerUtils(m_context).moveToStackVariable(_variableDeclarationStatement.getDeclaration()); } + checker.check(); return false; } bool Compiler::visit(ExpressionStatement const& _expressionStatement) { + StackHeightChecker checker(m_context); Expression const& expression = _expressionStatement.getExpression(); compileExpression(expression); CompilerUtils(m_context).popStackElement(*expression.getType()); + checker.check(); return false; } bool Compiler::visit(PlaceholderStatement const&) { + StackHeightChecker checker(m_context); ++m_modifierDepth; appendModifierOrFunctionCode(); --m_modifierDepth; + checker.check(); return true; } diff --git a/Compiler.h b/Compiler.h index 0838512ee..28ab34adb 100644 --- a/Compiler.h +++ b/Compiler.h @@ -69,7 +69,7 @@ private: virtual bool visit(Continue const& _continue) override; virtual bool visit(Break const& _break) override; virtual bool visit(Return const& _return) override; - virtual bool visit(VariableDeclarationStatement const& _variableDefinition) override; + virtual bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override; virtual bool visit(ExpressionStatement const& _expressionStatement) override; virtual bool visit(PlaceholderStatement const&) override; diff --git a/CompilerContext.h b/CompilerContext.h index f202d7f4e..da2e7f4fe 100644 --- a/CompilerContext.h +++ b/CompilerContext.h @@ -48,7 +48,7 @@ public: bytes const& getCompiledContract(ContractDefinition const& _contract) const; void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); } - unsigned getStackHeight() { solAssert(m_asm.deposit() >= 0, ""); return unsigned(m_asm.deposit()); } + unsigned getStackHeight() const { solAssert(m_asm.deposit() >= 0, ""); return unsigned(m_asm.deposit()); } bool isMagicGlobal(Declaration const* _declaration) const { return m_magicGlobals.count(_declaration) != 0; } bool isLocalVariable(Declaration const* _declaration) const; diff --git a/Types.cpp b/Types.cpp index 55dedd921..ce51336df 100644 --- a/Types.cpp +++ b/Types.cpp @@ -833,10 +833,17 @@ string FunctionType::toString() const unsigned FunctionType::getSizeOnStack() const { + Location location = m_location; + if (m_location == Location::SetGas || m_location == Location::SetValue) + { + solAssert(m_returnParameterTypes.size() == 1, ""); + location = dynamic_cast(*m_returnParameterTypes.front()).m_location; + } + unsigned size = 0; - if (m_location == Location::External) + if (location == Location::External) size = 2; - else if (m_location == Location::Internal || m_location == Location::Bare) + else if (location == Location::Internal || location == Location::Bare) size = 1; if (m_gasSet) size++;