Prevent instructions to be generated as names.

This commit is contained in:
chriseth 2019-04-24 13:38:35 +02:00
parent eac0048176
commit 0af8d758a5
6 changed files with 56 additions and 25 deletions

View File

@ -53,6 +53,27 @@ shared_ptr<Block> Parser::parse(std::shared_ptr<Scanner> const& _scanner, bool _
return nullptr;
}
std::map<string, dev::eth::Instruction> const& Parser::instructions()
{
// Allowed instructions, lowercase names.
static map<string, dev::eth::Instruction> s_instructions;
if (s_instructions.empty())
{
for (auto const& instruction: dev::eth::c_instructions)
{
if (
instruction.second == dev::eth::Instruction::JUMPDEST ||
dev::eth::isPushInstruction(instruction.second)
)
continue;
string name = instruction.first;
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
s_instructions[name] = instruction.second;
}
}
return s_instructions;
}
Block Parser::parseBlock()
{
RecursionGuard recursionGuard(*this);
@ -340,27 +361,6 @@ Expression Parser::parseExpression()
}
}
std::map<string, dev::eth::Instruction> const& Parser::instructions()
{
// Allowed instructions, lowercase names.
static map<string, dev::eth::Instruction> s_instructions;
if (s_instructions.empty())
{
for (auto const& instruction: dev::eth::c_instructions)
{
if (
instruction.second == dev::eth::Instruction::JUMPDEST ||
dev::eth::isPushInstruction(instruction.second)
)
continue;
string name = instruction.first;
transform(name.begin(), name.end(), name.begin(), [](unsigned char _c) { return tolower(_c); });
s_instructions[name] = instruction.second;
}
}
return s_instructions;
}
std::map<dev::eth::Instruction, string> const& Parser::instructionNames()
{
static map<dev::eth::Instruction, string> s_instructionNames;

View File

@ -46,6 +46,9 @@ public:
/// @returns an empty shared pointer on error.
std::shared_ptr<Block> parse(std::shared_ptr<langutil::Scanner> const& _scanner, bool _reuseScanner);
/// @returns a map of all EVM instructions available to assembly.
static std::map<std::string, dev::eth::Instruction> const& instructions();
protected:
using ElementaryOperation = boost::variant<Instruction, Literal, Identifier>;
@ -71,7 +74,6 @@ protected:
ForLoop parseForLoop();
/// Parses a functional expression that has to push exactly one stack element
Expression parseExpression();
static std::map<std::string, dev::eth::Instruction> const& instructions();
static std::map<dev::eth::Instruction, std::string> const& instructionNames();
/// Parses an elementary operation, i.e. a literal, identifier or instruction.
/// This will parse instructions even in strict mode as part of the full parser

View File

@ -23,6 +23,10 @@
#include <libyul/optimiser/NameCollector.h>
#include <libyul/AsmData.h>
#include <libyul/Dialect.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/AsmParser.h>
#include <libevmasm/Instruction.h>
using namespace std;
using namespace dev;
@ -42,7 +46,7 @@ NameDispenser::NameDispenser(Dialect const& _dialect, set<YulString> _usedNames)
YulString NameDispenser::newName(YulString _nameHint)
{
YulString name = _nameHint;
while (name.empty() || m_usedNames.count(name) || m_dialect.builtin(name))
while (illegalName(name))
{
m_counter++;
name = YulString(_nameHint.str() + "_" + to_string(m_counter));
@ -50,3 +54,12 @@ YulString NameDispenser::newName(YulString _nameHint)
m_usedNames.emplace(name);
return name;
}
bool NameDispenser::illegalName(YulString _name)
{
if (_name.empty() || m_usedNames.count(_name) || m_dialect.builtin(_name))
return true;
if (dynamic_cast<EVMDialect const*>(&m_dialect))
return Parser::instructions().count(_name.str());
return false;
}

View File

@ -47,6 +47,7 @@ public:
YulString newName(YulString _nameHint);
private:
bool illegalName(YulString _name);
Dialect const& m_dialect;
std::set<YulString> m_usedNames;

View File

@ -18,6 +18,8 @@
#include <libyul/optimiser/VarNameCleaner.h>
#include <libyul/AsmData.h>
#include <libyul/Dialect.h>
#include <libyul/AsmParser.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <algorithm>
#include <cctype>
#include <climits>
@ -93,7 +95,7 @@ void VarNameCleaner::operator()(Identifier& _identifier)
YulString VarNameCleaner::findCleanName(YulString const& _name) const
{
auto newName = stripSuffix(_name);
if (newName != YulString{} && !isUsedName(newName))
if (!isUsedName(newName))
return newName;
// create new name with suffix (by finding a free identifier)
@ -108,7 +110,11 @@ YulString VarNameCleaner::findCleanName(YulString const& _name) const
bool VarNameCleaner::isUsedName(YulString const& _name) const
{
return m_dialect.builtin(_name) || m_usedNames.count(_name);
if (_name.empty() || m_dialect.builtin(_name) || m_usedNames.count(_name))
return true;
if (dynamic_cast<EVMDialect const*>(&m_dialect))
return Parser::instructions().count(_name.str());
return false;
}
YulString VarNameCleaner::stripSuffix(YulString const& _name) const

View File

@ -0,0 +1,9 @@
{
let mul_256 := 1
}
// ====
// step: varNameCleaner
// ----
// {
// let mul_1 := 1
// }