Skip to content

Commit a3f8ba3

Browse files
committed
Check heredoc state for escaped newlines
When escaped newlines are encountered, they are added to the newline list. We need to check that we aren't backing up to read the rest of the line because of a heredoc, in which case the newline would have already have been added to the list.
1 parent c72817c commit a3f8ba3

2 files changed

Lines changed: 9 additions & 5 deletions

File tree

src/prism.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9064,7 +9064,7 @@ escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_
90649064
}
90659065

90669066
if (width == 1) {
9067-
if (*parser->current.end == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
9067+
if (parser->heredoc_end == NULL && *parser->current.end == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
90689068
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(*parser->current.end++, flags));
90699069
} else if (width > 1) {
90709070
// Valid multibyte character. Just ignore escape.
@@ -9381,7 +9381,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
93819381
return;
93829382
}
93839383

9384-
if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
9384+
if (parser->heredoc_end == NULL && peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
93859385
parser->current.end++;
93869386
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
93879387
return;
@@ -9440,7 +9440,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
94409440
return;
94419441
}
94429442

9443-
if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
9443+
if (parser->heredoc_end == NULL && peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
94449444
parser->current.end++;
94459445
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
94469446
return;
@@ -9494,15 +9494,15 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
94949494
return;
94959495
}
94969496

9497-
if (peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
9497+
if (parser->heredoc_end == NULL && peeked == '\n') pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 1);
94989498
parser->current.end++;
94999499
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META));
95009500
return;
95019501
}
95029502
}
95039503
case '\r': {
95049504
if (peek_offset(parser, 1) == '\n') {
9505-
pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2);
9505+
if (parser->heredoc_end == NULL) pm_line_offset_list_append(&parser->metadata_arena, &parser->line_offsets, PM_TOKEN_END(parser, &parser->current) + 2);
95069506
parser->current.end += 2;
95079507
escape_write_byte_encoded(parser, buffer, flags, escape_byte('\n', flags));
95089508
return;

test/prism/fuzzer_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,9 @@ def self.snippet(name, source)
6363
a
6464
/{/, ''\\
6565
RUBY
66+
67+
snippet "escaped newline in char literal after heredoc opener", "<<i=?\\\n\n\n"
68+
snippet "escaped newline in char literal after heredoc opener with operator", "<<T^?\\\n\n\n"
69+
snippet "control escape consuming newline after heredoc in interpolation", "%\n\#{<<e}\\c\n\n"
6670
end
6771
end

0 commit comments

Comments
 (0)