From d9093eab625c7a7029888e538c5474430fb1c110 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Sat, 29 Nov 2025 13:40:05 -0500 Subject: [PATCH 1/8] [ruby/tempfile] [DOC] Fix monofont for Tempfile.create https://github.com/ruby/tempfile/commit/96361e9e42 --- lib/tempfile.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tempfile.rb b/lib/tempfile.rb index 27ebb96439c7f3..eeed2534a917f7 100644 --- a/lib/tempfile.rb +++ b/lib/tempfile.rb @@ -550,7 +550,7 @@ def open(*args, **kw) # # Implementation note: # -# The keyword argument +anonymous=true+ is implemented using FILE_SHARE_DELETE on Windows. +# The keyword argument anonymous=true is implemented using FILE_SHARE_DELETE on Windows. # O_TMPFILE is used on Linux. # # Related: Tempfile.new. From 8a0ae3a71a8b12a5e5929a565ba98fdf7c16233b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Sat, 29 Nov 2025 13:42:16 -0500 Subject: [PATCH 2/8] [ruby/tempfile] [DOC] Monofont some text in Tempfile.create https://github.com/ruby/tempfile/commit/7fa7436baa --- lib/tempfile.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tempfile.rb b/lib/tempfile.rb index eeed2534a917f7..cd512bb1c5224b 100644 --- a/lib/tempfile.rb +++ b/lib/tempfile.rb @@ -550,8 +550,8 @@ def open(*args, **kw) # # Implementation note: # -# The keyword argument anonymous=true is implemented using FILE_SHARE_DELETE on Windows. -# O_TMPFILE is used on Linux. +# The keyword argument anonymous=true is implemented using +FILE_SHARE_DELETE+ on Windows. +# +O_TMPFILE+ is used on Linux. # # Related: Tempfile.new. # From 48a73303e45b1dbaa3422e14e35c7834db98be4d Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:13:04 +0100 Subject: [PATCH 3/8] [ruby/prism] Optimize `Prism::Source#find_line` This is more concise and ruby does a better job performance-wise. This used to be `bsearch_index` already but https://github.com/ruby/prism/commit/6d8358c08395438d5924777c1fc3001a5ebf0aa3 changed it. https://github.com/ruby/prism/pull/1733#discussion_r1373702087 said: > Yeah the edge case was that the value matched an element exactly But surely there would be a test to show this behaviour? Gets called as part of pretty-printing nodes. Further reduces the time for `SnapshotsTest` by ~16% for me. https://github.com/ruby/prism/commit/f448e2b995 --- lib/prism/parse_result.rb | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 05c14e33f5c99e..3570af136a4fb7 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -155,21 +155,8 @@ def deep_freeze # Binary search through the offsets to find the line number for the given # byte offset. def find_line(byte_offset) - left = 0 - right = offsets.length - 1 - - while left <= right - mid = left + (right - left) / 2 - return mid if (offset = offsets[mid]) == byte_offset - - if offset < byte_offset - left = mid + 1 - else - right = mid - 1 - end - end - - left - 1 + index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length + index - 1 end end From f2a6cb2dc88ca12938b45f35bc6e64d72060a959 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 29 Nov 2025 14:14:48 -0500 Subject: [PATCH 4/8] [ruby/prism] Handle invalid string pattern key When a pattern match is using a string as a hash pattern key and is using it incorrectly, we were previously assuming it was a symbol. In the case of an error, that's not the case. So we need to add a missing node in this case. https://github.com/ruby/prism/commit/f0b06d6269 --- prism/prism.c | 6 +++++- test/prism/errors/pattern_string_key.txt | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/prism/errors/pattern_string_key.txt diff --git a/prism/prism.c b/prism/prism.c index 186cdd354c9843..3485a58c28ee90 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17336,7 +17336,11 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node pm_node_t *value = NULL; if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); + if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) { + value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); + } else { + value = (pm_node_t *) pm_missing_node_create(parser, key->location.end, key->location.end); + } } else { value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1)); } diff --git a/test/prism/errors/pattern_string_key.txt b/test/prism/errors/pattern_string_key.txt new file mode 100644 index 00000000000000..9f28feddb96dea --- /dev/null +++ b/test/prism/errors/pattern_string_key.txt @@ -0,0 +1,8 @@ +case:a +in b:"","#{}" + ^~~~~ expected a label after the `,` in the hash pattern + ^ expected a pattern expression after the key + ^ expected a delimiter after the patterns of an `in` clause + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected an `end` to close the `case` statement + From f0f2a45f2d46fa4a0323ba5f29fba895b9e78f4b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 29 Nov 2025 14:20:06 -0500 Subject: [PATCH 5/8] [ruby/prism] Fix out-of-bounds read after utf-8 BOM https://github.com/ruby/prism/commit/198080c106 Co-authored-by: Steven Johnstone --- prism/prism.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 3485a58c28ee90..7d7072be79d76d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -22865,8 +22865,8 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm // If the shebang does not include "ruby" and this is the main script being // parsed, then we will start searching the file for a shebang that does // contain "ruby" as if -x were passed on the command line. - const uint8_t *newline = next_newline(parser->start, parser->end - parser->start); - size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start); + const uint8_t *newline = next_newline(parser->current.end, parser->end - parser->current.end); + size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->current.end); if (length > 2 && parser->current.end[0] == '#' && parser->current.end[1] == '!') { const char *engine; From 7c2eb946e04940901ee1957c3fb43897c661568e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 29 Nov 2025 14:28:36 -0500 Subject: [PATCH 6/8] [ruby/prism] Fix label interpolated string https://github.com/ruby/prism/commit/e3e2b1ed04 --- prism/config.yml | 3 +++ prism/prism.c | 6 ++++-- test/prism/errors/label_in_interpolated_string.txt | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/prism/errors/label_in_interpolated_string.txt diff --git a/prism/config.yml b/prism/config.yml index 3acab9f58d5d44..36becff28de508 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -3306,6 +3306,9 @@ nodes: - EmbeddedVariableNode - InterpolatedStringNode # `"a" "#{b}"` - on error: XStringNode # `<<`FOO` "bar" + - on error: InterpolatedXStringNode + - on error: SymbolNode + - on error: InterpolatedSymbolNode - name: closing_loc type: location? newline: parts diff --git a/prism/prism.c b/prism/prism.c index 7d7072be79d76d..6d10fcb1e46522 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5344,8 +5344,10 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_ break; case PM_X_STRING_NODE: case PM_INTERPOLATED_X_STRING_NODE: - // If this is an x string, then this is a syntax error. But we want - // to handle it here so that we don't fail the assertion. + case PM_SYMBOL_NODE: + case PM_INTERPOLATED_SYMBOL_NODE: + // These will only happen in error cases. But we want to handle it + // here so that we don't fail the assertion. CLEAR_FLAGS(node); break; default: diff --git a/test/prism/errors/label_in_interpolated_string.txt b/test/prism/errors/label_in_interpolated_string.txt new file mode 100644 index 00000000000000..e8f40dd2a8aa69 --- /dev/null +++ b/test/prism/errors/label_in_interpolated_string.txt @@ -0,0 +1,14 @@ +case in el""Q +^~~~ expected a predicate for a case matching statement + ^ expected a delimiter after the patterns of an `in` clause + ^ unexpected constant, expecting end-of-input + !"""#{in el"":Q + ^~ unexpected 'in', assuming it is closing the parent 'in' clause + ^ expected a `}` to close the embedded expression + ^~ cannot parse the string part + ^~ cannot parse the string part + ^ cannot parse the string part + ^~~~~~~~~~~ unexpected label + ^~~~~~~~~~~ expected a string for concatenation + ^ expected an `end` to close the `case` statement + From 748dc9ac8d68b7979936f171179c475c7f174953 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 29 Nov 2025 14:31:34 -0500 Subject: [PATCH 7/8] [ruby/prism] Fix out-of-bounds read in parser_lex_magic_comment https://github.com/ruby/prism/commit/e24e701f3a Co-authored-by: Steven Johnstone --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 6d10fcb1e46522..3d60e008c48a0a 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8445,7 +8445,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { if (*cursor == '\\' && (cursor + 1 < end)) cursor++; } value_end = cursor; - if (*cursor == '"') cursor++; + if (cursor < end && *cursor == '"') cursor++; } else { value_start = cursor; while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++; From e3bc1852b3a7bcacf3e18d1644fbea7839abe019 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 29 Nov 2025 15:51:06 -0500 Subject: [PATCH 8/8] [ruby/prism] Revert "Fix invalid Ruby code example in ClassNode comment" https://github.com/ruby/prism/commit/b960079559 --- prism/config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 36becff28de508..5e29d6fa181c34 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1860,7 +1860,7 @@ nodes: comment: | Represents the location of the `class` keyword. - class Foo; end + class Foo end ^^^^^ - name: constant_path type: node @@ -1899,19 +1899,19 @@ nodes: comment: | Represents the location of the `end` keyword. - class Foo; end - ^^^ + class Foo end + ^^^ - name: name type: constant comment: | The name of the class. - class Foo; end # name `:Foo` + class Foo end # name `:Foo` comment: | Represents a class declaration involving the `class` keyword. - class Foo; end - ^^^^^^^^^^^^^^ + class Foo end + ^^^^^^^^^^^^^ - name: ClassVariableAndWriteNode fields: - name: name