mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1224 from ethereum/inline-assembly-stack-warning
Issue inline assembly stack warning if not balanced
This commit is contained in:
commit
5875890576
@ -4,6 +4,7 @@ Features:
|
|||||||
|
|
||||||
* Inline assembly: support both ``suicide`` and ``selfdestruct`` opcodes
|
* Inline assembly: support both ``suicide`` and ``selfdestruct`` opcodes
|
||||||
(note: ``suicide`` is deprecated).
|
(note: ``suicide`` is deprecated).
|
||||||
|
* Inline assembly: issue warning if stack is not balanced after block.
|
||||||
* Include ``keccak256()`` as an alias to ``sha3()``.
|
* Include ``keccak256()`` as an alias to ``sha3()``.
|
||||||
* Support shifting constant numbers.
|
* Support shifting constant numbers.
|
||||||
|
|
||||||
|
@ -718,11 +718,10 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
|||||||
{
|
{
|
||||||
if (ref->dataStoredIn(DataLocation::Storage))
|
if (ref->dataStoredIn(DataLocation::Storage))
|
||||||
{
|
{
|
||||||
auto err = make_shared<Error>(Error::Type::Warning);
|
warning(
|
||||||
*err <<
|
varDecl.location(),
|
||||||
errinfo_sourceLocation(varDecl.location()) <<
|
"Uninitialized storage pointer. Did you mean '<type> memory " + varDecl.name() + "'?"
|
||||||
errinfo_comment("Uninitialized storage pointer. Did you mean '<type> memory " + varDecl.name() + "'?");
|
);
|
||||||
m_errors.push_back(err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
varDecl.accept(*this);
|
varDecl.accept(*this);
|
||||||
|
@ -575,7 +575,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
solAssert(errors.empty(), "Code generation for inline assembly with errors requested.");
|
solAssert(Error::containsOnlyWarnings(errors), "Code generation for inline assembly with errors requested.");
|
||||||
m_context.setStackOffset(startStackHeight);
|
m_context.setStackOffset(startStackHeight);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <libsolidity/inlineasm/AsmCodeGen.h>
|
#include <libsolidity/inlineasm/AsmCodeGen.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <libdevcore/CommonIO.h>
|
||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
#include <libevmasm/SourceLocation.h>
|
#include <libevmasm/SourceLocation.h>
|
||||||
#include <libevmasm/Instruction.h>
|
#include <libevmasm/Instruction.h>
|
||||||
@ -213,10 +214,31 @@ public:
|
|||||||
void operator()(assembly::Block const& _block)
|
void operator()(assembly::Block const& _block)
|
||||||
{
|
{
|
||||||
size_t numVariables = m_state.variables.size();
|
size_t numVariables = m_state.variables.size();
|
||||||
|
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));
|
||||||
// pop variables
|
deposit = m_state.assembly.deposit() - deposit;
|
||||||
// we deliberately do not check stack height
|
|
||||||
m_state.assembly.setSourceLocation(_block.location);
|
m_state.assembly.setSourceLocation(_block.location);
|
||||||
|
|
||||||
|
// issue warnings for stack height discrepancies
|
||||||
|
if (deposit < 0)
|
||||||
|
{
|
||||||
|
m_state.addError(
|
||||||
|
Error::Type::Warning,
|
||||||
|
"Inline assembly block is not balanced. It takes " + toString(-deposit) + " item(s) from the stack.",
|
||||||
|
_block.location
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (deposit > 0)
|
||||||
|
{
|
||||||
|
m_state.addError(
|
||||||
|
Error::Type::Warning,
|
||||||
|
"Inline assembly block is not balanced. It leaves " + toString(deposit) + " item(s) on the stack.",
|
||||||
|
_block.location
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pop variables
|
||||||
while (m_state.variables.size() > numVariables)
|
while (m_state.variables.size() > numVariables)
|
||||||
{
|
{
|
||||||
m_state.assembly.append(solidity::Instruction::POP);
|
m_state.assembly.append(solidity::Instruction::POP);
|
||||||
|
@ -51,7 +51,7 @@ bool successParse(std::string const& _source, bool _assemble = false)
|
|||||||
if (_assemble)
|
if (_assemble)
|
||||||
{
|
{
|
||||||
stack.assemble();
|
stack.assemble();
|
||||||
if (!stack.errors().empty())
|
if (!stack.errors().empty() && !Error::containsOnlyWarnings(stack.errors()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4079,6 +4079,34 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue)
|
|||||||
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract test {
|
||||||
|
function f() {
|
||||||
|
assembly {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract test {
|
||||||
|
function f() {
|
||||||
|
assembly {
|
||||||
|
pop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user