ruby-changes:56018
From: Nobuyoshi <ko1@a...>
Date: Wed, 5 Jun 2019 13:35:05 +0900 (JST)
Subject: [ruby-changes:56018] Nobuyoshi Nakada: 1624d77f3e (trunk): error.c: avoid infinite recursion at inspecting the frozen object
https://git.ruby-lang.org/ruby.git/commit/?id=1624d77f3e From 1624d77f3ee0a536a6ab37da014d85d16fcd1de2 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Wed, 5 Jun 2019 13:02:38 +0900 Subject: error.c: avoid infinite recursion at inspecting the frozen object diff --git a/error.c b/error.c index 1e1af77..19265f6 100644 --- a/error.c +++ b/error.c @@ -2887,24 +2887,37 @@ rb_frozen_error_raise(VALUE frozen_obj, const char *fmt, ...) https://github.com/ruby/ruby/blob/trunk/error.c#L2887 rb_exc_raise(exc); } +static VALUE +inspect_frozen_obj(VALUE obj, VALUE mesg, int recur) +{ + if (recur) { + rb_str_cat_cstr(mesg, " ..."); + } + else { + rb_str_append(mesg, rb_inspect(obj)); + } + return mesg; +} + void rb_error_frozen_object(VALUE frozen_obj) { VALUE debug_info; const ID created_info = id_debug_created_info; + VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ", + CLASS_OF(frozen_obj)); + VALUE exc = rb_exc_new_str(rb_eFrozenError, mesg); + + rb_ivar_set(exc, id_recv, frozen_obj); + rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg); if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) { VALUE path = rb_ary_entry(debug_info, 0); VALUE line = rb_ary_entry(debug_info, 1); - rb_frozen_error_raise(frozen_obj, - "can't modify frozen %"PRIsVALUE": %"PRIsVALUE", created at %"PRIsVALUE":%"PRIsVALUE, - CLASS_OF(frozen_obj), rb_inspect(frozen_obj), path, line); - } - else { - rb_frozen_error_raise(frozen_obj, "can't modify frozen %"PRIsVALUE": %"PRIsVALUE, - CLASS_OF(frozen_obj), rb_inspect(frozen_obj)); + rb_str_catf(mesg, ", created at %"PRIsVALUE":%"PRIsVALUE, path, line); } + rb_exc_raise(exc); } #undef rb_check_frozen diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 54e39a0..c69d18b 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -886,6 +886,21 @@ end.join https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L886 obj.instance_variable_set(:@test, true) } assert_include(e.message, obj.inspect) + + klass = Class.new do + def init + @x = true + end + def inspect + init + super + end + end + obj = klass.new.freeze + e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { + obj.init + } + assert_include(e.message, klass.inspect) end def test_name_error_new_default -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/