Project

General

Profile

Actions

Bug #17405

closed

irb ---nomultiline gets exception when output contains some non-ascii characters

Added by rsharman (Richard Sharman) 4 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Target version:
-
ruby -v:
ruby 3.0.0dev (2020-12-21T02:23:01Z master ac78d90d5e) [x86_64-darwin18]
[ruby-core:101513]

Description

When irb is called with the --nomultiline option (for example, when called from emacs), then if the output contains some special characters (such as the square root sign, or a single quotation mark), then irb gets an exception.

Without the --multiline option the problem does not happen.

Here is an example with a string assignment to variable m.

Without fix: Without --nomultiline there is no problem:

henry:tmp richard$ irb
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
=> "√10"
test.rb(main):004:0> m
=> "√10"
=> nil

But with --nomultiline irb gets an exception (but the assignment did work):

henry:tmp richard$ irb --nomultiline
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
Traceback (most recent call last):
8: from /Users/richard/.rbenv/versions/2.7.2/bin/irb:23:in <main>'
7: from /Users/richard/.rbenv/versions/2.7.2/bin/irb:23:in
load'
6: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in <top (required)>'
5: from (irb):1
4: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:99:in
calculate_width'
3: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:99:in scan'
2: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:108:in
block in calculate_width'
1: from /Users/richard/.rbenv/versions/2.7.2/lib/ruby/2.7.0/reline/unicode.rb:108:in `+'
TypeError (nil can't be coerced into Integer)
test.rb(main):004:0> m
=> "√10"
=> nil

The problem is that in method get_mbchar_width of class Reline::Unicode Reline.ambiguous_width can have a nil value, whereas the code seems to expect a low integer (unicode.rb line 84). This causes method calculate_width to add a nil value to width (line 109).

I don’t know what value Reline.ambiguous_width should be in these cases; the simple change below uses a value of 1 to avoid the exception:

bash-5.1$ diff unicode.rb{.orig,}
84c84,85
<       Reline.ambiguous_width
---
>       width = Reline.ambiguous_width
>       width.nil? ? 1 : width  # if nil then assume 1
bash-5.1$


With above fix:

henry:tmp richard$ irb --nomultiline
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
=> "√10"
test.rb(main):004:0> m
=> "√10"
=> nil
henry:tmp richard$


Files

test.rb (30 Bytes) test.rb Test file -- source this in irb rsharman (Richard Sharman), 12/18/2020 05:49 PM
Patch (456 Bytes) Patch Suggested patch (unified diff format) rsharman (Richard Sharman), 12/18/2020 05:49 PM

Updated by ima1zumi (Mari Imaizumi) 4 months ago

Thank you for your notice.
However, this bug has already been fixed in the latest version.

❯ bin/console --nomultiline
irb(main):002:0> Reline::VERSION
=> "0.1.10"
irb(main):003:0> source 'test.rb'
test.rb(main):004:0> # coding: utf-8
=> nil
test.rb(main):005:0> m = "√10"
test.rb(main):006:0> m
=> "√10"
=> nil

Updated by marcandre (Marc-Andre Lafortune) 4 months ago

  • ruby -v changed from ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin17] to ruby 3.0.0dev (2020-12-21T02:23:01Z master ac78d90d5e) [x86_64-darwin18]
  • Assignee set to aycabta (aycabta .)

I can reproduce on master. Maybe platform dependent?

Hopefully aycabta (aycabta .) will figure something out...

$ ruby -v
ruby 3.0.0dev (2020-12-21T02:23:01Z master ac78d90d5e) [x86_64-darwin18]
$ irb --nomultiline
irb(main):001:0> Reline::VERSION
=> "0.1.10"
irb(main):001:0> source 'test.rb'
test.rb(main):002:0> # coding: utf-8
=> nil
test.rb(main):003:0> m = "√10"
Traceback (most recent call last):
        8: from /Users/mal/.rbenv/versions/3/bin/irb:23:in `<main>'
        7: from /Users/mal/.rbenv/versions/3/bin/irb:23:in `load'
        6: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/gems/3.0.0/gems/irb-1.2.8/exe/irb:11:in `<top (required)>'
        5: from (irb):1:in `<main>'
        4: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:126:in `calculate_width'
        3: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:126:in `scan'
        2: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:136:in `block in calculate_width'
        1: from /Users/mal/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/reline/unicode.rb:136:in `+'
TypeError (nil can't be coerced into Integer)
test.rb(main):004:0> m
=> "√10"
=> nil

Updated by aycabta (aycabta .) 4 months ago

rsharman (Richard Sharman) and marcandre (Marc-Andre Lafortune), would you show me the result of irb_info command in IRB and what terminal emulator you are using?

Updated by aycabta (aycabta .) 4 months ago

And, does https://github.com/ruby/reline/pull/224 resolve the problem? I can't reproduce in my environment...

Updated by marcandre (Marc-Andre Lafortune) 4 months ago

aycabta (aycabta .) wrote in #note-3:

rsharman (Richard Sharman) and marcandre (Marc-Andre Lafortune), would you show me the result of irb_info command in IRB and what terminal emulator you are using?

irb(main):001:0> irb_info
=>
Ruby version: 3.0.0
IRB version: irb 1.2.8 (2020-12-20)
InputMethod: ReidlineInputMethod with Reline 0.1.10
.irbrc path: /Users/mal/.irbrc

Using iTerm2, Build 3.4.3, but reproduced also on Terminal.app Version 2.9.5 (421.2)

If Richard Sharman can try your patch that would be great, lots of things I'd like to finish before 3.0

Updated by osyo (manga osyo) 4 months ago

hi.

This error is caused by calling Reline::Unicode.calculate_width in irb.
Reline::Unicode.calculate_width should be initialized with #may_req_ambiguous_char_width inside Reline.
However, in the case of --nomultiline, #may_req_ambiguous_char_width is not called and is not initialized because Reline is not used.
This was causing the call to Reline::Unicode.calculate_width to fail, resulting in an error.
This problem has been solved by explicitly calling #may_req_ambiguous_char_width inside Reline::Unicode.calculate_width.

PR is merged : https://github.com/ruby/reline/pull/224

Actions #7

Updated by ima1zumi (Mari Imaizumi) 4 months ago

  • Status changed from Open to Closed

Applied in changeset git|299f5708a2274d069c624073ca3958f8625faf35.


[ruby/reline] Fixed an exception occurred when ambiguous width character was passed to #calculate_width [Bug #17405]

https://github.com/ruby/reline/commit/f79b4c857f

Updated by rsharman (Richard Sharman) 4 months ago

Sorry not to have checked back recently. The patch mentioned above works great for me.
I doubt if this is required now but here it is:
irb(main):001:0> irb_info
=>
Ruby version: 2.7.2
IRB version: irb 1.2.6 (2020-09-14)
InputMethod: ReidlineInputMethod with Reline 0.1.5
.irbrc path: /Users/richard/.irbrc

irb(main):002:0>

Actions

Also available in: Atom PDF