From 7aab72f7367b81fa76fcb4e9281012134495d6cf Mon Sep 17 00:00:00 2001 From: tenderlove Date: Mon, 9 Jul 2018 17:47:37 +0000 Subject: [PATCH] Fix crash when loading iseq from an array Objects loaded during iseq deserialization using arrays need to be added to the compile time mark array so that they stay alive until iseqs finish loading. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63920 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 14 ++++++++++---- test/-ext-/iseq_load/test_iseq_load.rb | 7 +++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compile.c b/compile.c index 6cd25ef3af..d9d072b3a2 100644 --- a/compile.c +++ b/compile.c @@ -2159,6 +2159,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, body->is_size); } generated_iseq[code_index + 1 + j] = (VALUE)ic; + RB_OBJ_WRITTEN(iseq, Qundef, ic); FL_SET(iseq, ISEQ_MARKABLE_ISEQ); break; } @@ -7914,11 +7915,14 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, break; case TS_VALUE: argv[j] = op; + iseq_add_mark_object_compile_time(iseq, op); break; case TS_ISEQ: { if (op != Qnil) { - argv[j] = (VALUE)iseq_build_load_iseq(iseq, op); + VALUE v = (VALUE)iseq_build_load_iseq(iseq, op); + argv[j] = v; + iseq_add_mark_object_compile_time(iseq, v); } else { argv[j] = 0; @@ -7929,8 +7933,9 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, op = rb_to_symbol_type(op); argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); break; - case TS_IC: case TS_ISE: + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + case TS_IC: argv[j] = op; if (NUM2UINT(op) >= iseq->body->is_size) { iseq->body->is_size = NUM2INT(op) + 1; @@ -7961,6 +7966,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, } RB_GC_GUARD(op); argv[j] = map; + iseq_add_mark_object_compile_time(iseq, map); } break; case TS_FUNCPTR: @@ -8655,9 +8661,9 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct r } break; } - case TS_IC: - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); case TS_ISE: + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + case TS_IC: code[code_index] = (VALUE)&is_entries[(int)op]; break; case TS_CALLINFO: diff --git a/test/-ext-/iseq_load/test_iseq_load.rb b/test/-ext-/iseq_load/test_iseq_load.rb index 97ba3fec66..7a8120ad1c 100644 --- a/test/-ext-/iseq_load/test_iseq_load.rb +++ b/test/-ext-/iseq_load/test_iseq_load.rb @@ -16,6 +16,13 @@ class TestIseqLoad < Test::Unit::TestCase end; end + def test_stressful_roundtrip + stress, GC.stress = GC.stress, true + test_bug8543 + ensure + GC.stress = stress + end + def test_case_when assert_iseq_roundtrip "#{<<~"begin;"}\n#{<<~'end;'}" begin;