Skip to content

Commit 0424c1f

Browse files
kddnewtonmatzbot
authored andcommitted
[ruby/prism] Fix up embdoc lexing on EOF
ruby/prism@8ee43be26d
1 parent 9bab179 commit 0424c1f

File tree

3 files changed

+30
-13
lines changed

3 files changed

+30
-13
lines changed

prism/prism.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9605,15 +9605,23 @@ lex_embdoc(pm_parser_t *parser) {
96059605
pm_comment_t *comment = parser_comment(parser, PM_COMMENT_EMBDOC);
96069606
if (comment == NULL) return PM_TOKEN_EOF;
96079607

9608-
// Now, loop until we find the end of the embedded documentation or the end of
9609-
// the file.
9608+
// Now, loop until we find the end of the embedded documentation or the end
9609+
// of the file.
96109610
while (parser->current.end + 4 <= parser->end) {
96119611
parser->current.start = parser->current.end;
96129612

9613-
// If we've hit the end of the embedded documentation then we'll return that
9614-
// token here.
9615-
if (memcmp(parser->current.end, "=end", 4) == 0 &&
9616-
(parser->current.end + 4 == parser->end || pm_char_is_whitespace(parser->current.end[4]))) {
9613+
// If we've hit the end of the embedded documentation then we'll return
9614+
// that token here.
9615+
if (
9616+
(memcmp(parser->current.end, "=end", 4) == 0) &&
9617+
(
9618+
(parser->current.end + 4 == parser->end) || // end of file
9619+
pm_char_is_whitespace(parser->current.end[4]) || // whitespace
9620+
(parser->current.end[4] == '\0') || // NUL or end of script
9621+
(parser->current.end[4] == '\004') || // ^D
9622+
(parser->current.end[4] == '\032') // ^Z
9623+
)
9624+
) {
96179625
const uint8_t *newline = next_newline(parser->current.end, parser->end - parser->current.end);
96189626

96199627
if (newline == NULL) {
@@ -10425,9 +10433,13 @@ parser_lex(pm_parser_t *parser) {
1042510433

1042610434
// = => =~ == === =begin
1042710435
case '=':
10428-
if (current_token_starts_line(parser) && (parser->current.end + 5 <= parser->end) && memcmp(parser->current.end, "begin", 5) == 0 && pm_char_is_whitespace(peek_offset(parser, 5))) {
10436+
if (
10437+
current_token_starts_line(parser) &&
10438+
(parser->current.end + 5 <= parser->end) &&
10439+
memcmp(parser->current.end, "begin", 5) == 0 &&
10440+
(pm_char_is_whitespace(peek_offset(parser, 5)) || (peek_offset(parser, 5) == '\0'))
10441+
) {
1042910442
pm_token_type_t type = lex_embdoc(parser);
10430-
1043110443
if (type == PM_TOKEN_EOF) {
1043210444
LEX(type);
1043310445
}

prism/templates/src/diagnostic.c.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
152152
[PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_LEVEL_SYNTAX },
153153
[PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_LEVEL_SYNTAX },
154154
[PM_ERR_DEFINED_EXPRESSION] = { "expected an expression after `defined?`", PM_ERROR_LEVEL_SYNTAX },
155-
[PM_ERR_EMBDOC_TERM] = { "could not find a terminator for the embedded document", PM_ERROR_LEVEL_SYNTAX },
155+
[PM_ERR_EMBDOC_TERM] = { "embedded document meets end of file", PM_ERROR_LEVEL_SYNTAX },
156156
[PM_ERR_EMBEXPR_END] = { "expected a `}` to close the embedded expression", PM_ERROR_LEVEL_SYNTAX },
157157
[PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_LEVEL_SYNTAX },
158158
[PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_LEVEL_SYNTAX },

test/prism/errors_test.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ def test_pre_execution_context
105105
end
106106

107107
def test_unterminated_embdoc
108-
assert_errors expression("1"), "1\n=begin\n", [
109-
["could not find a terminator for the embedded document", 2..9]
110-
]
108+
message = "embedded document meets end of file"
109+
assert_error_messages "=begin", [message]
110+
assert_error_messages "=begin\n", [message]
111+
112+
refute_error_messages "=begin\n=end"
113+
refute_error_messages "=begin\n=end\0"
114+
refute_error_messages "=begin\n=end\C-d"
115+
refute_error_messages "=begin\n=end\C-z"
111116
end
112117

113118
def test_unterminated_i_list
@@ -2217,7 +2222,7 @@ def assert_error_messages(source, errors)
22172222

22182223
def refute_error_messages(source)
22192224
assert_valid_syntax(source)
2220-
assert Prism.parse_success?(source)
2225+
assert Prism.parse_success?(source), "Expected #{source.inspect} to parse successfully"
22212226
end
22222227

22232228
def assert_warning_messages(source, warnings)

0 commit comments

Comments
 (0)