From 15517b571d3ac4ee01af3e2e2f3fff7c5b2296c5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 13 Oct 2017 02:04:36 +0100 Subject: [PATCH] lll: disallow useless PUSHn in assembly --- liblll/CodeFragment.cpp | 44 ++++++++++++++++++++++++---------------- test/liblll/Compiler.cpp | 17 ++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index d4ef38883dc2..5c68194b4205 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -47,6 +47,32 @@ void CodeFragment::finalise(CompilerState const& _cs) } } +namespace +{ +/// Returns true iff the instruction is valid in "inline assembly". +bool validAssemblyInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) + ); +} + +/// Returns true iff the instruction is valid as a function. +bool validFunctionalInstruction(string us) +{ + auto it = c_instructions.find(us); + return !( + it == c_instructions.end() || + solidity::isPushInstruction(it->second) || + solidity::isDupInstruction(it->second) || + solidity::isSwapInstruction(it->second) || + it->second == solidity::Instruction::JUMPDEST + ); +} +} + CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback const& _readFile, bool _allowASM): m_readFile(_readFile) { @@ -80,7 +106,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback auto sr = _t.get, sp::utree_type::symbol_type>>(); string s(sr.begin(), sr.end()); string us = boost::algorithm::to_upper_copy(s); - if (_allowASM && c_instructions.count(us)) + if (_allowASM && c_instructions.count(us) && validAssemblyInstruction(us)) m_asm.append(c_instructions.at(us)); else if (_s.defs.count(s)) m_asm.append(_s.defs.at(s).m_asm); @@ -114,22 +140,6 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback } } -namespace -{ -/// Returns true iff the instruction is valid as a function. -bool validFunctionalInstruction(string us) -{ - auto it = c_instructions.find(us); - return !( - it == c_instructions.end() || - solidity::isPushInstruction(it->second) || - solidity::isDupInstruction(it->second) || - solidity::isSwapInstruction(it->second) || - it->second == solidity::Instruction::JUMPDEST - ); -} -} - void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { if (_t.tag() == 0 && _t.empty()) diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index 2d66bce1fe4f..77d263b8d08c 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -121,6 +121,23 @@ BOOST_AUTO_TEST_CASE(switch_inconsistent_return_count) BOOST_CHECK(!successCompile(sourceCode)); } +BOOST_AUTO_TEST_CASE(disallowed_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(asm PUSH" + boost::lexical_cast(i) + ")")); +} + +BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions) +{ + for (unsigned i = 1; i <= 32; i++) + BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast(i) + ")")); + for (unsigned i = 1; i <= 16; i++) + BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast(i) + ")")); + BOOST_CHECK(!successCompile("(JUMPDEST)")); +} + BOOST_AUTO_TEST_SUITE_END() }