From 0af8d758a537dc233f1aba074dfa70071ba54e8e Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 24 Apr 2019 13:38:35 +0200 Subject: [PATCH] Prevent instructions to be generated as names. --- libyul/AsmParser.cpp | 42 +++++++++---------- libyul/AsmParser.h | 4 +- libyul/optimiser/NameDispenser.cpp | 15 ++++++- libyul/optimiser/NameDispenser.h | 1 + libyul/optimiser/VarNameCleaner.cpp | 10 ++++- .../varNameCleaner/instructions.yul | 9 ++++ 6 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index a7787ebe4..9ea909ae8 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -53,6 +53,27 @@ shared_ptr Parser::parse(std::shared_ptr const& _scanner, bool _ return nullptr; } +std::map const& Parser::instructions() +{ + // Allowed instructions, lowercase names. + static map 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 const& Parser::instructions() -{ - // Allowed instructions, lowercase names. - static map 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 const& Parser::instructionNames() { static map s_instructionNames; diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 5985f1f93..4a7880de5 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -46,6 +46,9 @@ public: /// @returns an empty shared pointer on error. std::shared_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); + /// @returns a map of all EVM instructions available to assembly. + static std::map const& instructions(); + protected: using ElementaryOperation = boost::variant; @@ -71,7 +74,6 @@ protected: ForLoop parseForLoop(); /// Parses a functional expression that has to push exactly one stack element Expression parseExpression(); - static std::map const& instructions(); static std::map 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 diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index 52a115874..2a0c1e44f 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -23,6 +23,10 @@ #include #include #include +#include +#include + +#include using namespace std; using namespace dev; @@ -42,7 +46,7 @@ NameDispenser::NameDispenser(Dialect const& _dialect, set _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(&m_dialect)) + return Parser::instructions().count(_name.str()); + return false; +} diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 6b61596fe..9591dd135 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -47,6 +47,7 @@ public: YulString newName(YulString _nameHint); private: + bool illegalName(YulString _name); Dialect const& m_dialect; std::set m_usedNames; diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index 81532c136..4c3946295 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -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(&m_dialect)) + return Parser::instructions().count(_name.str()); + return false; } YulString VarNameCleaner::stripSuffix(YulString const& _name) const diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul b/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul new file mode 100644 index 000000000..7c5aca950 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul @@ -0,0 +1,9 @@ +{ + let mul_256 := 1 +} +// ==== +// step: varNameCleaner +// ---- +// { +// let mul_1 := 1 +// }