From 0158de60bebda81e8f2ca87e9393e38e335e8a84 Mon Sep 17 00:00:00 2001 From: Matheus Aguiar Date: Mon, 20 Mar 2023 16:49:39 -0300 Subject: [PATCH] Refactored NumberUnit and FunctionDefinition. Added OctalNumber. Fixed number followed by identifier with no whitespace. --- Changelog.md | 3 +++ docs/grammar/SolidityLexer.g4 | 16 +++++++++++- docs/grammar/SolidityParser.g4 | 26 +++++++++++++++---- .../invalid_denomination_no_whitespace.sol | 5 ++++ .../two_denominations_same_literal.sol | 5 ++++ .../freeFunctions/named_fallback_warning.sol | 3 +++ .../freeFunctions/named_receive_warning.sol | 3 +++ .../literals/invalid_hex_number.sol | 5 ++++ ...valid_octal_denomination_no_whitespace.sol | 5 ++++ .../literals/invalid_octal_digits.sol | 5 ++++ .../literals/invalid_octal_number.sol | 5 ++++ 11 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 test/libsolidity/syntaxTests/denominations/invalid_denomination_no_whitespace.sol create mode 100644 test/libsolidity/syntaxTests/denominations/two_denominations_same_literal.sol create mode 100644 test/libsolidity/syntaxTests/freeFunctions/named_fallback_warning.sol create mode 100644 test/libsolidity/syntaxTests/freeFunctions/named_receive_warning.sol create mode 100644 test/libsolidity/syntaxTests/literals/invalid_hex_number.sol create mode 100644 test/libsolidity/syntaxTests/literals/invalid_octal_denomination_no_whitespace.sol create mode 100644 test/libsolidity/syntaxTests/literals/invalid_octal_digits.sol create mode 100644 test/libsolidity/syntaxTests/literals/invalid_octal_number.sol diff --git a/Changelog.md b/Changelog.md index f51aaffb2..6c17c147b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,9 @@ Compiler Features: Bugfixes: + * Antlr Grammar: Fix discrepancy with the parser, which allowed octal numbers. + * Antlr Grammar: Fix of a discrepancy with the parser, which allowed numbers followed by an identifier with no whitespace. + * Antlr Grammar: Stricter rules for function definitions. The grammar will no longer accept as valid free functions having specifiers which are exclusive to contract functions. ### 0.8.19 (2023-02-22) diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index e1d0da6a9..306afd92f 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -62,7 +62,7 @@ New: 'new'; /** * Unit denomination for numbers. */ -NumberUnit: 'wei' | 'gwei' | 'ether' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years'; +SubDenomination: 'wei' | 'gwei' | 'ether' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years'; Override: 'override'; Payable: 'payable'; Pragma: 'pragma' -> pushMode(PragmaMode); @@ -220,6 +220,14 @@ fragment EvenHexDigits: HexCharacter HexCharacter ('_'? HexCharacter HexCharacte //@doc:inline fragment HexCharacter: [0-9A-Fa-f]; +/** + * Scanned but not used by any rule, i.e, disallowed. + * solc parser considers number starting with '0', not immediately followed by '.' or 'x' as + * octal, even if non octal digits '8' and '9' are present. + */ +OctalNumber: '0' DecimalDigits ('.' DecimalDigits)?; + + /** * A decimal number literal consists of decimal digits that may be delimited by underscores and * an optional positive or negative exponent. @@ -230,6 +238,12 @@ DecimalNumber: (DecimalDigits | (DecimalDigits? '.' DecimalDigits)) ([eE] '-'? D fragment DecimalDigits: [0-9] ('_'? [0-9])* ; +/** + * This is needed to avoid successfully parsing a number followed by a string with no whitespace between. + */ +DecimalNumberFollowedByIdentifier: DecimalNumber Identifier; + + /** * An identifier in solidity has to start with a letter, a dollar-sign or an underscore and * may additionally contain numbers after the first symbol. diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 673f1c071..d2ef74cff 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -16,7 +16,7 @@ sourceUnit: ( | contractDefinition | interfaceDefinition | libraryDefinition - | functionDefinition + | freeFunctionDefinition | constantVariableDeclaration | structDefinition | enumDefinition @@ -85,7 +85,7 @@ inheritanceSpecifier: name=identifierPath arguments=callArgumentList?; */ contractBodyElement: constructorDefinition - | functionDefinition + | contractFunctionDefinition | modifierDefinition | fallbackFunctionDefinition | receiveFunctionDefinition @@ -156,12 +156,12 @@ overrideSpecifier: Override (LParen overrides+=identifierPath (Comma overrides+= * Depending on the context in which the function is defined, further restrictions may apply, * e.g. functions in interfaces have to be unimplemented, i.e. may not contain a body block. */ -functionDefinition +contractFunctionDefinition locals[ boolean visibilitySet = false, boolean mutabilitySet = false, boolean virtualSet = false, - boolean overrideSpecifierSet = false + boolean overrideSpecifierSet = false, ] : Function (identifier | Fallback | Receive) @@ -175,6 +175,17 @@ locals[ )* (Returns LParen returnParameters=parameterList RParen)? (Semicolon | body=block); + +/** + * The definition of a free function. + */ + freeFunctionDefinition: + Function (identifier | Fallback | Receive) + LParen (arguments=parameterList)? RParen + stateMutability? + (Returns LParen returnParameters=parameterList RParen)? + (Semicolon | body=block); + /** * The definition of a modifier. * Note that within the body block of a modifier, the underscore cannot be used as identifier, @@ -394,6 +405,7 @@ expression: | ( identifier | literal + | literalWithSubDenomination | elementaryTypeName[false] ) # PrimaryExpression ; @@ -412,6 +424,9 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; identifier: Identifier | From | Error | Revert | Global; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; + +literalWithSubDenomination: numberLiteral SubDenomination; + booleanLiteral: True | False; /** * A full string literal consists of either one or several consecutive quoted strings. @@ -429,7 +444,8 @@ unicodeStringLiteral: UnicodeStringLiteral+; /** * Number literals can be decimal or hexadecimal numbers with an optional unit. */ -numberLiteral: (DecimalNumber | HexNumber) NumberUnit?; +numberLiteral: DecimalNumber | HexNumber; + /** * A curly-braced block of statements. Opens its own scope. */ diff --git a/test/libsolidity/syntaxTests/denominations/invalid_denomination_no_whitespace.sol b/test/libsolidity/syntaxTests/denominations/invalid_denomination_no_whitespace.sol new file mode 100644 index 000000000..f67fde89d --- /dev/null +++ b/test/libsolidity/syntaxTests/denominations/invalid_denomination_no_whitespace.sol @@ -0,0 +1,5 @@ +contract C { + uint constant y = 1wei; +} +// ---- +// ParserError 8936: (32-33): Identifier-start is not allowed at end of a number. diff --git a/test/libsolidity/syntaxTests/denominations/two_denominations_same_literal.sol b/test/libsolidity/syntaxTests/denominations/two_denominations_same_literal.sol new file mode 100644 index 000000000..8583e1d42 --- /dev/null +++ b/test/libsolidity/syntaxTests/denominations/two_denominations_same_literal.sol @@ -0,0 +1,5 @@ +contract C { + uint constant y = 8 gwei ether; +} +// ---- +// ParserError 2314: (39-44): Expected ';' but got 'ether' diff --git a/test/libsolidity/syntaxTests/freeFunctions/named_fallback_warning.sol b/test/libsolidity/syntaxTests/freeFunctions/named_fallback_warning.sol new file mode 100644 index 000000000..8f0c0ea3f --- /dev/null +++ b/test/libsolidity/syntaxTests/freeFunctions/named_fallback_warning.sol @@ -0,0 +1,3 @@ +function fallback() {} +// ---- +// Warning 3445: (9-17): This function is named "fallback" but is not the fallback function of the contract. If you intend this to be a fallback function, use "fallback(...) { ... }" without the "function" keyword to define it. diff --git a/test/libsolidity/syntaxTests/freeFunctions/named_receive_warning.sol b/test/libsolidity/syntaxTests/freeFunctions/named_receive_warning.sol new file mode 100644 index 000000000..25c860241 --- /dev/null +++ b/test/libsolidity/syntaxTests/freeFunctions/named_receive_warning.sol @@ -0,0 +1,3 @@ +function receive() {} +// ---- +// Warning 3445: (9-16): This function is named "receive" but is not the receive function of the contract. If you intend this to be a receive function, use "receive(...) { ... }" without the "function" keyword to define it. diff --git a/test/libsolidity/syntaxTests/literals/invalid_hex_number.sol b/test/libsolidity/syntaxTests/literals/invalid_hex_number.sol new file mode 100644 index 000000000..1cc7e0ecc --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/invalid_hex_number.sol @@ -0,0 +1,5 @@ +contract C { + uint x = 0x1000abcdefgh; +} +// ---- +// ParserError 8936: (26-38): Identifier-start is not allowed at end of a number. diff --git a/test/libsolidity/syntaxTests/literals/invalid_octal_denomination_no_whitespace.sol b/test/libsolidity/syntaxTests/literals/invalid_octal_denomination_no_whitespace.sol new file mode 100644 index 000000000..a4ec101c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/invalid_octal_denomination_no_whitespace.sol @@ -0,0 +1,5 @@ +contract C { + uint y = 01gwei; +} +// ---- +// ParserError 8936: (26-27): Octal numbers not allowed. diff --git a/test/libsolidity/syntaxTests/literals/invalid_octal_digits.sol b/test/libsolidity/syntaxTests/literals/invalid_octal_digits.sol new file mode 100644 index 000000000..8565377a0 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/invalid_octal_digits.sol @@ -0,0 +1,5 @@ +contract C { + uint y = 098; +} +// ---- +// ParserError 8936: (26-27): Octal numbers not allowed. diff --git a/test/libsolidity/syntaxTests/literals/invalid_octal_number.sol b/test/libsolidity/syntaxTests/literals/invalid_octal_number.sol new file mode 100644 index 000000000..668913be6 --- /dev/null +++ b/test/libsolidity/syntaxTests/literals/invalid_octal_number.sol @@ -0,0 +1,5 @@ +contract C { + uint x = 0100; +} +// ---- +// ParserError 8936: (26-27): Octal numbers not allowed.