diff --git a/Changelog.md b/Changelog.md index d670209ad..6126ea6d4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * SMTChecker: Fix internal error on fixed bytes index access. * References Resolver: Fix internal bug when using constructor for library. * Yul Optimizer: Make function inlining order more resilient to whether or not unrelated source files are present. + * Yul Optimizer: Ensure that Yul keywords are not mistakenly used by the NameDispenser and VarNameCleaners. The bug would manifest as uncompilable code. * Type Checker: Disallow signed literals as exponent in exponentiation operator. * Allow `type(Contract).name` for abstract contracts and interfaces. * Type Checker: Disallow structs containing nested mapping in memory as parameters for library functions. diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 70b645992..bbcfe1590 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -152,6 +152,11 @@ static Token keywordByName(string const& _name) return it == keywords.end() ? Token::Identifier : it->second; } +bool isYulKeyword(string const& _literal) +{ + return _literal == "leave" || isYulKeyword(keywordByName(_literal)); +} + tuple fromIdentifierOrKeyword(string const& _literal) { auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit); diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 2bfc58e44..3d9c71ab3 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -327,6 +327,8 @@ namespace TokenTraits tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex; } + bool isYulKeyword(std::string const& _literal); + inline Token AssignmentToBinaryOp(Token op) { solAssert(isAssignmentOp(op) && op != Token::Assign, ""); diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index ec091b2d7..eaf9b8b4b 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -22,8 +22,10 @@ #include #include +#include #include #include +#include #include @@ -57,7 +59,5 @@ YulString NameDispenser::newName(YulString _nameHint) bool NameDispenser::illegalName(YulString _name) { - if (_name.empty() || m_usedNames.count(_name) || m_dialect.builtin(_name)) - return true; - return false; + return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); } diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 3cb66d689..ad46f7cb1 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -21,15 +21,19 @@ #include +#include #include +#include #include #include using namespace std; using namespace solidity; +using namespace solidity::langutil; using namespace solidity::util; +using namespace solidity::yul; void yul::removeEmptyBlocks(Block& _block) { @@ -38,3 +42,8 @@ void yul::removeEmptyBlocks(Block& _block) }; boost::range::remove_erase_if(_block.statements, isEmptyBlock); } + +bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier) +{ + return _identifier.empty() || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.builtin(_identifier); +} diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 61d970877..829d10b55 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -23,6 +23,8 @@ #include #include +#include +#include namespace solidity::yul { @@ -30,4 +32,8 @@ namespace solidity::yul /// Removes statements that are just empty blocks (non-recursive). void removeEmptyBlocks(Block& _block); +/// Returns true if a given literal can not be used as an identifier. +/// This includes Yul keywords and builtins of the given dialect. +bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier); + } diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index edea33d2b..85ecece46 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -17,6 +17,7 @@ // SPDX-License-Identifier: GPL-3.0 #include +#include #include #include @@ -110,9 +111,7 @@ YulString VarNameCleaner::findCleanName(YulString const& _name) const bool VarNameCleaner::isUsedName(YulString const& _name) const { - if (_name.empty() || m_dialect.builtin(_name) || m_usedNames.count(_name)) - return true; - return false; + return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); } YulString VarNameCleaner::stripSuffix(YulString const& _name) const