mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Prevent instructions to be generated as names.
This commit is contained in:
parent
eac0048176
commit
0af8d758a5
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
YulString newName(YulString _nameHint);
|
||||
|
||||
private:
|
||||
bool illegalName(YulString _name);
|
||||
|
||||
Dialect const& m_dialect;
|
||||
std::set<YulString> m_usedNames;
|
||||
|
@ -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
|
||||
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
let mul_256 := 1
|
||||
}
|
||||
// ====
|
||||
// step: varNameCleaner
|
||||
// ----
|
||||
// {
|
||||
// let mul_1 := 1
|
||||
// }
|
Loading…
Reference in New Issue
Block a user