Issue #18367 has been updated by mame (Yusuke Endoh).

Dan0042 (Daniel DeLorme) wrote in #note-7:
> I'm not sure it makes sense to allow ANSI escapes that can _only_ result in broken formatting.

Good point. If you want to control attribution, I think you have to reset it by \e[0m at the beginning and control everything yourself.

> What about just removing the backslash from the set of escaped characters? For most errors it can be misleading, as in the example of "\\".no_method above.

@nobu is against this because it becomes ambiguous.

----------------------------------------
Feature #18367: Stop the interpreter from escaping error messages
https://bugs.ruby-lang.org/issues/18367#change-94992

* Author: mame (Yusuke Endoh)
* Status: Open
* Priority: Normal
----------------------------------------
## Proposal

At the present time, the Ruby interpreter escapes some characters (*1) in error messages when an uncaught error is printed. I'd like to propose stopping this escaping behavior.


class MyError < StandardError
def message
"foo\\bar"
end
end

raise MyError
#=> current:  test.rb:7: in <main>': foo\\bar (MyError)
#=> excepted: test.rb:7: in <main>': foo\bar (MyError)


*1: Escaped characters are any control characters except \r and \n, and a backslash \\.

## Motivation

This behavior prevents us from adding an attribution (color, underline, etc.) to the error message because it escapes escape sequences. Nowadays, such a rich presentation of terminal output is more and more important.


$ruby -e 'raise "\e[31mRed\x1b[0m error"' -e:1:in <main>': \e[31mRed\x1b[0m error (RuntimeError)  Also, the behavior in question leads to rather confusing error printing. See the error output of "\\".no_method: $ ruby -e '"\\".no_method'
-e:1:in <main>': undefined method no_method' for "\\\\":String (NoMethodError)

"\\\\".no_method
^^^^^^^^^^


The two occurrences of "\\\\" must be "\\". Worse, the output of error_highlight ^^^^ points wrong position.

Note that this issue is never specific to error_highlight. The receiver of NoMethodError, "\\\\":String, is also wrongly escaped. It must be "\\":String.

## Why the escaping behavior was introduced

AFAIK, the behavior was introduced because of a security concern. It is considered harmful for an attacker to be able to print arbitrary escape sequences to victim's terminal. (See [this article](https://marc.info/?l=bugtraq&m=104612710031920&w=2) in detail.)

However, I believe it is rare to see the error logs of an application that may be exposed to attacks (i.e. in production mode) in a terminal, as the error output of the Ruby interpreter.

Even if that is the case, I think such escaping should be done as a responsibility of the application, and not implicitly by the interpreter. I briefly surveyed other major languages than Ruby, and I could find no language that escapes error messages. This is the transcript of Python and Node.js.


$python3 -c 'raise Exception("\x1b[31mRed\x1b[0m error")' Traceback (most recent call last): File "<string>", line 1, in <module> Exception: Red error$ node -e 'throw("\x1b[31mRed\x1b[0m error")'

[eval]:1
throw("\x1b[31mRed\x1b[0m error")
^
Red error
(Use node --trace-uncaught ... to show where the exception was thrown)


Just in case, I reported these behaviors to the security contacts of Python and Node.js, and both responded to me that this is not a securty issue. I think their decisions are quite reasonable.

## Migration

It would be a good idea to first make the following behavior as a migration path.

* When an error message does not include a control character, no escaping is applied.
* When an error message does include a control character, "Warning: this error message is currently escaped because it includes a control character(s), but this will not be escaped in Ruby 3.X" is printed, and the escaping is applied.

--
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
`