Merge pull request #1375 from ethereum/inline-assembly-stack-height

Fix inline assembly stack warnings when using variables
This commit is contained in:
chriseth 2016-11-15 11:25:12 +01:00 committed by GitHub
commit 028ab1fbfb
3 changed files with 23 additions and 12 deletions

View File

@ -7,6 +7,7 @@ Features:
Bugfixes: Bugfixes:
* Inline assembly: calculate stack height warning correctly even when local variables are used.
* Parser: disallow empty enum definitions. * Parser: disallow empty enum definitions.
* Type checker: disallow conversion between different enum types. * Type checker: disallow conversion between different enum types.
* Interface JSON: do not include trailing new line. * Interface JSON: do not include trailing new line.

View File

@ -216,10 +216,18 @@ public:
size_t numVariables = m_state.variables.size(); size_t numVariables = m_state.variables.size();
int deposit = m_state.assembly.deposit(); int deposit = m_state.assembly.deposit();
std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this)); std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this));
deposit = m_state.assembly.deposit() - deposit;
// pop variables
while (m_state.variables.size() > numVariables)
{
m_state.assembly.append(solidity::Instruction::POP);
m_state.variables.pop_back();
}
m_state.assembly.setSourceLocation(_block.location); m_state.assembly.setSourceLocation(_block.location);
deposit = m_state.assembly.deposit() - deposit;
// issue warnings for stack height discrepancies // issue warnings for stack height discrepancies
if (deposit < 0) if (deposit < 0)
{ {
@ -238,12 +246,6 @@ public:
); );
} }
// pop variables
while (m_state.variables.size() > numVariables)
{
m_state.assembly.append(solidity::Instruction::POP);
m_state.variables.pop_back();
}
} }
private: private:

View File

@ -41,7 +41,7 @@ namespace test
namespace namespace
{ {
bool successParse(std::string const& _source, bool _assemble = false) bool successParse(std::string const& _source, bool _assemble = false, bool _allowWarnings = true)
{ {
assembly::InlineAssemblyStack stack; assembly::InlineAssemblyStack stack;
try try
@ -51,8 +51,9 @@ bool successParse(std::string const& _source, bool _assemble = false)
if (_assemble) if (_assemble)
{ {
stack.assemble(); stack.assemble();
if (!stack.errors().empty() && !Error::containsOnlyWarnings(stack.errors())) if (!stack.errors().empty())
return false; if (!_allowWarnings || !Error::containsOnlyWarnings(stack.errors()))
return false;
} }
} }
catch (FatalError const&) catch (FatalError const&)
@ -67,9 +68,9 @@ bool successParse(std::string const& _source, bool _assemble = false)
return true; return true;
} }
bool successAssemble(string const& _source) bool successAssemble(string const& _source, bool _allowWarnings = true)
{ {
return successParse(_source, true); return successParse(_source, true, _allowWarnings);
} }
} }
@ -169,6 +170,13 @@ BOOST_AUTO_TEST_CASE(magic_variables)
BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }")); BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }"));
} }
BOOST_AUTO_TEST_CASE(imbalanced_stack)
{
BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false));
BOOST_CHECK(!successAssemble("{ 1 }", false));
BOOST_CHECK(successAssemble("{ let x := 4 7 add }", false));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }