diff --git a/prism_compile.c b/prism_compile.c index 2f5bb4ebe3..b7edc6b48e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -10706,6 +10706,21 @@ pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t * start += column_start; } + // Take care to not produce a string that is invalid in its encoding. + if (truncate_end) { + const uint8_t *end_adjusted = start; + while (end_adjusted < end) { + const size_t next_width = pm_encoding_utf_8_char_width(end_adjusted, 4); + // We should only get here with valid utf-8 + RUBY_ASSERT(next_width > 0); + + if (end_adjusted + next_width > end) { + end = end_adjusted; + } + end_adjusted += next_width; + } + } + pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); if (truncate_end) { diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index b7e021a4ff..66ebc247b5 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require 'test/unit' +require_relative '../lib/parser_support' class TestSyntax < Test::Unit::TestCase using Module.new { @@ -1069,6 +1070,22 @@ eom assert_syntax_error("/(?[)/=~s", /premature end of char-class/, bug20295) end + def test_syntax_error_message_truncation + omit unless ParserSupport.prism_enabled? + + bug21528 = '[ruby-core:122899] [Bug #21528]' + begin + eval(<<~CODE) + if a + # 0000000000000ああああああ + # + CODE + rescue SyntaxError => e + assert(e.message.valid_encoding?) + assert_include(e.message, "# 0000000000000あああああ ...") + end + end + def test_lineno_operation_brace_block expected = __LINE__ + 1 actual = caller_lineno\