diff options
author | nagachika <nagachika@ruby-lang.org> | 2023-03-25 11:04:33 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2023-03-25 11:04:33 +0900 |
commit | 810ae06c06312908fc1a7284773d8a9101ee145b (patch) | |
tree | 5b9dd70da37a85caac30c80e71b5dbc4efd08665 | |
parent | 8c99882dad0b6fedbd656889829a3780366bd8b6 (diff) | |
download | ruby-810ae06c06312908fc1a7284773d8a9101ee145b.tar.gz |
merge revision(s) 2e7e153a2af1456515d43b6381e38534b069b1c2: [Backport #19242]
[Bug #19242] Prohibit circular causes to be loaded
---
error.c | 4 ++++
eval.c | 4 ++++
eval_error.c | 11 +++++++++++
test/ruby/test_exception.rb | 12 ++++++++++++
4 files changed, 31 insertions(+)
-rw-r--r-- | error.c | 4 | ||||
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | eval_error.c | 11 | ||||
-rw-r--r-- | test/ruby/test_exception.rb | 12 | ||||
-rw-r--r-- | version.h | 2 |
5 files changed, 32 insertions, 1 deletions
@@ -2846,6 +2846,8 @@ ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc) return ST_CONTINUE; } +void rb_exc_check_circular_cause(VALUE exc); + static VALUE exception_loader(VALUE exc, VALUE obj) { @@ -2860,6 +2862,8 @@ exception_loader(VALUE exc, VALUE obj) rb_ivar_foreach(obj, ivar_copy_i, exc); + rb_exc_check_circular_cause(exc); + if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) { rb_ivar_set(exc, id_bt_locations, Qnil); } @@ -528,12 +528,16 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause) } if (!nocircular && !NIL_P(*cause) && *cause != Qundef && *cause != mesg) { +#if 0 /* maybe critical for some cases */ + rb_exc_check_circular_cause(*cause); +#else VALUE c = *cause; while (!NIL_P(c = rb_attr_get(c, id_cause))) { if (c == mesg) { rb_raise(rb_eArgError, "circular causes"); } } +#endif } return mesg; } diff --git a/eval_error.c b/eval_error.c index 9b453eede0..1baa4484a0 100644 --- a/eval_error.c +++ b/eval_error.c @@ -311,6 +311,17 @@ show_cause(VALUE errinfo, VALUE str, VALUE highlight, VALUE reverse, long backtr } void +rb_exc_check_circular_cause(VALUE exc) +{ + VALUE cause = exc, shown_causes = 0; + do { + if (shown_cause_p(cause, &shown_causes)) { + rb_raise(rb_eArgError, "circular causes"); + } + } while (!NIL_P(cause = rb_attr_get(cause, id_cause))); +} + +void rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlight, VALUE reverse) { volatile VALUE eclass; diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index f99bb230a3..ffca877f1e 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -1412,6 +1412,18 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end; end + def test_marshal_circular_cause + begin + raise RuntimeError, "err", [], cause: Exception.new + rescue => e + end + dump = Marshal.dump(e).sub(/o:\x0EException\x08;.0;.0;.0/, "@\x05") + assert_raise_with_message(ArgumentError, /circular cause/, ->{dump.inspect}) do + e = Marshal.load(dump) + assert_same(e, e.cause) + end + end + def test_super_in_method_missing assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 4 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 212 +#define RUBY_PATCHLEVEL 213 #define RUBY_RELEASE_YEAR 2023 #define RUBY_RELEASE_MONTH 3 |