diff --git a/lib/irb.rb b/lib/irb.rb index 93c4d25c92..4b06f897da 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -590,9 +590,15 @@ module IRB end end - def convert_invalid_byte_sequence(str) - str = str.force_encoding(Encoding::ASCII_8BIT) - conv = Encoding::Converter.new(Encoding::ASCII_8BIT, Encoding::UTF_8) + def convert_invalid_byte_sequence(str, enc) + str.force_encoding(enc) + str.scrub { |c| + c.bytes.map{ |b| "\\x#{b.to_s(16).upcase}" }.join + } + end + + def encode_with_invalid_byte_sequence(str, enc) + conv = Encoding::Converter.new(str.encoding, enc) dst = String.new begin ret = conv.primitive_convert(str, dst) @@ -640,7 +646,8 @@ module IRB message = exc.full_message(order: :top) order = :top end - message = convert_invalid_byte_sequence(message) + message = convert_invalid_byte_sequence(message, exc.message.encoding) + message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) if message.encoding != IRB.conf[:LC_MESSAGES].encoding message = message.gsub(/((?:^\t.+$\n)+)/) { |m| case order when :top diff --git a/test/irb/test_raise_no_backtrace_exception.rb b/test/irb/test_raise_no_backtrace_exception.rb index 40ee0c52bf..925f39a81c 100644 --- a/test/irb/test_raise_no_backtrace_exception.rb +++ b/test/irb/test_raise_no_backtrace_exception.rb @@ -21,5 +21,30 @@ IRB raise StandardError, "A\\xf3B" IRB end + + def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence + skip if RUBY_ENGINE == 'truffleruby' + backup_home = ENV["HOME"] + Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir| + ENV["HOME"] = tmpdir + + bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : [] + File.open('euc.rb', 'w') do |f| + f.write(<<~EOF) + # encoding: euc-jp + + def raise_euc_with_invalid_byte_sequence + raise "\xA4\xA2\\xFF" + end + EOF + end + assert_in_out_err(bundle_exec + %w[-rirb -W0 -e ENV[%(LC_ALL)]=%(ja_JP.UTF-8) -e ENV[%(LANG)]=%(ja_JP.UTF-8) -e IRB.start(__FILE__) -- -f --], <<~IRB, /`raise_euc_with_invalid_byte_sequence': あ\\xFF \(RuntimeError\)/, []) + require_relative 'euc' + raise_euc_with_invalid_byte_sequence + IRB + end + ensure + ENV["HOME"] = backup_home + end end end