Stack height checks and fix.

This commit is contained in:
Christian 2015-02-22 18:38:32 +01:00
parent c62828c8ff
commit e7528c6af8
4 changed files with 47 additions and 8 deletions

View File

@ -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<ContractDefinition const*, bytes const*> 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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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<FunctionType const&>(*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++;