diff --git a/Changelog.md b/Changelog.md index dc7dcc94c..1d3212e18 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Breaking changes: * Type Checker: Exponentiation and shifts of literals by non-literals will always use ``uint256`` or ``int256`` as a type. * Type Checker: Disallow structs and arrays in memory or calldata if they contain nested mappings. * Type Checker: Disallow assignments to state variables that contain nested mappings. + * Inline Assembly: Disallow `.` in user-defined function and variable names. Language Features: * Yul: Disallow EVM instruction `pc()`. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 408a7ff83..a0d70fd8f 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -38,9 +38,8 @@ using namespace std; using namespace solidity::langutil; +using namespace solidity::frontend; -namespace solidity::frontend -{ bool ReferencesResolver::resolve(ASTNode const& _root) { @@ -184,6 +183,10 @@ bool ReferencesResolver::visit(Return const& _return) void ReferencesResolver::operator()(yul::FunctionDefinition const& _function) { + validateYulIdentifierName(_function.name, _function.location); + for (yul::TypedName const& varName: _function.parameters + _function.returnVariables) + validateYulIdentifierName(varName.name, varName.location); + bool wasInsideFunction = m_yulInsideFunction; m_yulInsideFunction = true; this->operator()(_function.body); @@ -249,6 +252,8 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl) { for (auto const& identifier: _varDecl.variables) { + validateYulIdentifierName(identifier.name, identifier.location); + bool isSlot = boost::algorithm::ends_with(identifier.name.str(), "_slot"); bool isOffset = boost::algorithm::ends_with(identifier.name.str(), "_offset"); @@ -283,4 +288,12 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl) visit(*_varDecl.value); } +void ReferencesResolver::validateYulIdentifierName(yul::YulString _name, SourceLocation const& _location) +{ + if (util::contains(_name.str(), '.')) + m_errorReporter.declarationError( + 3927_error, + _location, + "User-defined identifiers in inline assembly cannot contain '.'." + ); } diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 7da745cc5..6b496eda9 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -88,6 +88,9 @@ private: void operator()(yul::Identifier const& _identifier) override; void operator()(yul::VariableDeclaration const& _varDecl) override; + /// Checks if the name contains a '.'. + void validateYulIdentifierName(yul::YulString _name, langutil::SourceLocation const& _location); + langutil::ErrorReporter& m_errorReporter; NameAndTypeResolver& m_resolver; langutil::EVMVersion m_evmVersion; diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fun_param.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fun_param.sol new file mode 100644 index 000000000..e6644e9da --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fun_param.sol @@ -0,0 +1,12 @@ +contract C { + function f() public pure { + assembly { + function f(a., x.b) -> t.b, b.. {} + } + } +} +// ---- +// DeclarationError 3927: (74-76): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (78-81): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (86-89): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (91-94): User-defined identifiers in inline assembly cannot contain '.'. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fundecl.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fundecl.sol new file mode 100644 index 000000000..2e8118b78 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_fundecl.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + function f.() {} + function g.f() {} + } + } +} +// ---- +// DeclarationError 3927: (63-79): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (86-103): User-defined identifiers in inline assembly cannot contain '.'. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_multi_vardecl.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_multi_vardecl.sol new file mode 100644 index 000000000..58efb2de6 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_multi_vardecl.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + assembly { + function f() -> x, y, z {} + let a., aa.b := f() + } + } +} +// ---- +// DeclarationError 3927: (100-102): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (104-108): User-defined identifiers in inline assembly cannot contain '.'. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_vardecl.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_vardecl.sol new file mode 100644 index 000000000..0537afb74 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/dot_in_vardecl.sol @@ -0,0 +1,15 @@ +contract C { + function f() public pure { + assembly { + let a. := 2 + let a.. := 2 + let a.b := 2 + let a..b := 2 + } + } +} +// ---- +// DeclarationError 3927: (67-69): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (85-88): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (104-107): User-defined identifiers in inline assembly cannot contain '.'. +// DeclarationError 3927: (123-127): User-defined identifiers in inline assembly cannot contain '.'. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/identifier_starting_with_dot.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/identifier_starting_with_dot.sol new file mode 100644 index 000000000..0122dc4db --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/identifier_starting_with_dot.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + let a, .a, aa.b := f() + } + } +} +// ---- +// ParserError 2314: (70-71): Expected identifier but got '.' diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/name_clash_in_import.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/name_clash_in_import.sol index 50a1b749c..e0ae12e95 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/name_clash_in_import.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/name_clash_in_import.sol @@ -15,4 +15,5 @@ contract B { } // ---- // DeclarationError 3859: (b:105-106): This declaration shadows a declaration outside the inline assembly block. +// DeclarationError 3927: (b:128-131): User-defined identifiers in inline assembly cannot contain '.'. // DeclarationError 3859: (b:128-131): The prefix of this declaration conflicts with a declaration outside the inline assembly block. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/no_name_clash_in_import.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/no_name_clash_in_import.sol index 86426aad9..bb593da64 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/no_name_clash_in_import.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/no_name_clash_in_import.sol @@ -9,7 +9,6 @@ contract B { function f() public pure { assembly { let A := 1 - let A.b := 2 } } } diff --git a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/qualified_names.sol b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/qualified_names.sol index 7fba010f5..2f54bab68 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/shadowing/qualified_names.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/shadowing/qualified_names.sol @@ -10,5 +10,7 @@ contract C { } } // ---- +// DeclarationError 3927: (115-118): User-defined identifiers in inline assembly cannot contain '.'. // DeclarationError 3859: (115-118): The prefix of this declaration conflicts with a declaration outside the inline assembly block. +// DeclarationError 3927: (140-143): User-defined identifiers in inline assembly cannot contain '.'. // DeclarationError 3859: (140-143): The prefix of this declaration conflicts with a declaration outside the inline assembly block.