Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions liblll/CodeFragment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -80,7 +106,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, ReadCallback
auto sr = _t.get<sp::basic_string<boost::iterator_range<char const*>, 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);
Expand Down Expand Up @@ -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())
Expand Down
17 changes: 17 additions & 0 deletions test/liblll/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>(i) + ")"));
}

BOOST_AUTO_TEST_CASE(disallowed_functional_asm_instructions)
{
for (unsigned i = 1; i <= 32; i++)
BOOST_CHECK(!successCompile("(PUSH" + boost::lexical_cast<string>(i) + ")"));
for (unsigned i = 1; i <= 16; i++)
BOOST_CHECK(!successCompile("(DUP" + boost::lexical_cast<string>(i) + ")"));
for (unsigned i = 1; i <= 16; i++)
BOOST_CHECK(!successCompile("(SWAP" + boost::lexical_cast<string>(i) + ")"));
BOOST_CHECK(!successCompile("(JUMPDEST)"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@winsvega wanted to use (JUMPDEST) in some tests. He and @axic need to talk.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can still be used via assembly: (asm JUMPDEST). See #3066.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then it's a non-issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note it was removed a week ago or so, this PR removes pushnn from assembly and adds tests for the rest too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is an issue. some tests rely on (JUMPDEST)
and we dont have a unit test that actually checks that all lll opcodes are actually supported by lllc version before running the test fillers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pirapira what are the options?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We build just parser of (opcode) to bytecode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the older version of solidity lllc works just like that. if you suggest to write a new parser...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The older version of lllc is buggy and it produces unreliable output, at least output which we shouldn't rely on in testing the entire ecosystem with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@winsvega either fork an older lllc and fix the bugs, or create a new compiler.

}

BOOST_AUTO_TEST_SUITE_END()

}
Expand Down