[ruby/prism] Reject invalid rational literals like 1e1r on lexing

Fix https://github.com/ruby/prism/pull/1586

https://github.com/ruby/prism/commit/b3bde866f2
This commit is contained in:
TSUYUSATO Kitsune 2023-11-12 11:13:31 +09:00 committed by git
parent e6916f1305
commit 2fb1d37439
3 changed files with 52 additions and 39 deletions

View File

@ -6315,7 +6315,7 @@ pm_strspn_hexadecimal_number_validate(pm_parser_t *parser, const uint8_t *string
}
static pm_token_type_t
lex_optional_float_suffix(pm_parser_t *parser) {
lex_optional_float_suffix(pm_parser_t *parser, bool* seen_e) {
pm_token_type_t type = PM_TOKEN_INTEGER;
// Here we're going to attempt to parse the optional decimal portion of a
@ -6336,6 +6336,7 @@ lex_optional_float_suffix(pm_parser_t *parser) {
// float. If it's not there, it's okay and we'll just continue on.
if (match(parser, 'e') || match(parser, 'E')) {
(void) (match(parser, '+') || match(parser, '-'));
*seen_e = true;
if (pm_char_is_decimal_digit(*parser->current.end)) {
parser->current.end++;
@ -6351,8 +6352,9 @@ lex_optional_float_suffix(pm_parser_t *parser) {
}
static pm_token_type_t
lex_numeric_prefix(pm_parser_t *parser) {
lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) {
pm_token_type_t type = PM_TOKEN_INTEGER;
*seen_e = false;
if (peek_offset(parser, -1) == '0') {
switch (*parser->current.end) {
@ -6423,14 +6425,14 @@ lex_numeric_prefix(pm_parser_t *parser) {
// 0.xxx is a float
case '.': {
type = lex_optional_float_suffix(parser);
type = lex_optional_float_suffix(parser, seen_e);
break;
}
// 0exxx is a float
case 'e':
case 'E': {
type = lex_optional_float_suffix(parser);
type = lex_optional_float_suffix(parser, seen_e);
break;
}
}
@ -6440,7 +6442,7 @@ lex_numeric_prefix(pm_parser_t *parser) {
parser->current.end += pm_strspn_decimal_number_validate(parser, parser->current.end);
// Afterward, we'll lex as far as we can into an optional float suffix.
type = lex_optional_float_suffix(parser);
type = lex_optional_float_suffix(parser, seen_e);
}
return type;
@ -6452,7 +6454,8 @@ lex_numeric(pm_parser_t *parser) {
parser->integer_base = PM_INTEGER_BASE_FLAGS_DECIMAL;
if (parser->current.end < parser->end) {
type = lex_numeric_prefix(parser);
bool seen_e = false;
type = lex_numeric_prefix(parser, &seen_e);
const uint8_t *end = parser->current.end;
pm_token_type_t suffix_type = type;
@ -6468,7 +6471,7 @@ lex_numeric(pm_parser_t *parser) {
suffix_type = PM_TOKEN_INTEGER_IMAGINARY;
}
} else {
if (match(parser, 'r')) {
if (!seen_e && match(parser, 'r')) {
suffix_type = PM_TOKEN_FLOAT_RATIONAL;
if (match(parser, 'i')) {

View File

@ -44,10 +44,14 @@
1ri
1.2r
1.2ri
-1ri
-1.2r
-1.2ri
0o1r

View File

@ -1,8 +1,8 @@
@ ProgramNode (location: (1,0)-(63,5))
@ ProgramNode (location: (1,0)-(67,5))
├── locals: []
└── statements:
@ StatementsNode (location: (1,0)-(63,5))
└── body: (length: 32)
@ StatementsNode (location: (1,0)-(67,5))
└── body: (length: 34)
├── @ IntegerNode (location: (1,0)-(1,1))
│ └── flags: decimal
├── @ IntegerNode (location: (3,0)-(3,1))
@ -56,47 +56,53 @@
│ └── numeric:
│ @ IntegerNode (location: (45,0)-(45,1))
│ └── flags: decimal
├── @ ImaginaryNode (location: (47,0)-(47,5))
├── @ RationalNode (location: (47,0)-(47,4))
│ └── numeric:
│ @ RationalNode (location: (47,0)-(47,4))
│ └── numeric:
│ @ FloatNode (location: (47,0)-(47,3))
├── @ ImaginaryNode (location: (49,0)-(49,4))
│ @ FloatNode (location: (47,0)-(47,3))
├── @ ImaginaryNode (location: (49,0)-(49,5))
│ └── numeric:
│ @ RationalNode (location: (49,0)-(49,3))
│ @ RationalNode (location: (49,0)-(49,4))
│ └── numeric:
│ @ IntegerNode (location: (49,0)-(49,2))
│ @ FloatNode (location: (49,0)-(49,3))
├── @ ImaginaryNode (location: (51,0)-(51,4))
│ └── numeric:
│ @ RationalNode (location: (51,0)-(51,3))
│ └── numeric:
│ @ IntegerNode (location: (51,0)-(51,2))
│ └── flags: decimal
├── @ ImaginaryNode (location: (51,0)-(51,6))
├── @ RationalNode (location: (53,0)-(53,5))
│ └── numeric:
│ @ RationalNode (location: (51,0)-(51,5))
│ @ FloatNode (location: (53,0)-(53,4))
├── @ ImaginaryNode (location: (55,0)-(55,6))
│ └── numeric:
│ @ RationalNode (location: (55,0)-(55,5))
│ └── numeric:
│ @ FloatNode (location: (51,0)-(51,4))
├── @ RationalNode (location: (53,0)-(53,4))
│ @ FloatNode (location: (55,0)-(55,4))
├── @ RationalNode (location: (57,0)-(57,4))
│ └── numeric:
│ @ IntegerNode (location: (53,0)-(53,3))
│ @ IntegerNode (location: (57,0)-(57,3))
│ └── flags: octal
├── @ ImaginaryNode (location: (55,0)-(55,4))
│ └── numeric:
│ @ IntegerNode (location: (55,0)-(55,3))
│ └── flags: octal
├── @ ImaginaryNode (location: (57,0)-(57,5))
│ └── numeric:
│ @ RationalNode (location: (57,0)-(57,4))
│ └── numeric:
│ @ IntegerNode (location: (57,0)-(57,3))
│ └── flags: octal
├── @ RationalNode (location: (59,0)-(59,4))
├── @ ImaginaryNode (location: (59,0)-(59,4))
│ └── numeric:
│ @ IntegerNode (location: (59,0)-(59,3))
│ └── flags: decimal
├── @ ImaginaryNode (location: (61,0)-(61,4))
│ └── flags: octal
├── @ ImaginaryNode (location: (61,0)-(61,5))
│ └── numeric:
│ @ IntegerNode (location: (61,0)-(61,3))
│ @ RationalNode (location: (61,0)-(61,4))
│ └── numeric:
│ @ IntegerNode (location: (61,0)-(61,3))
│ └── flags: octal
├── @ RationalNode (location: (63,0)-(63,4))
│ └── numeric:
│ @ IntegerNode (location: (63,0)-(63,3))
│ └── flags: decimal
└── @ ImaginaryNode (location: (63,0)-(63,5))
├── @ ImaginaryNode (location: (65,0)-(65,4))
│ └── numeric:
│ @ IntegerNode (location: (65,0)-(65,3))
│ └── flags: decimal
└── @ ImaginaryNode (location: (67,0)-(67,5))
└── numeric:
@ RationalNode (location: (63,0)-(63,4))
@ RationalNode (location: (67,0)-(67,4))
└── numeric:
@ IntegerNode (location: (63,0)-(63,3))
@ IntegerNode (location: (67,0)-(67,3))
└── flags: binary