[前][次][番号順一覧][スレッド一覧]

ruby-changes:64870

From: Aaron <ko1@a...>
Date: Thu, 14 Jan 2021 09:14:09 +0900 (JST)
Subject: [ruby-changes:64870] efcdf68e64 (master): Guard callinfo

https://git.ruby-lang.org/ruby.git/commit/?id=efcdf68e64

From efcdf68e6443ab70fbff1703b9dabbfc5090df31 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Wed, 13 Jan 2021 13:35:11 -0800
Subject: Guard callinfo

Callinfo was being written in to an array and the GC would not see the
reference on the stack.  `new_insn_send` creates a new callinfo object,
then it calls `new_insn_core`.  `new_insn_core` allocates a new INSN
linked list item, which can end up calling `xmalloc` which will trigger
a GC:

  https://github.com/ruby/ruby/blob/70cd351c7c71c48ee18d7c01e851a89614086f8f/compile.c#L968-L969

Since the callinfo object isn't on the stack, the GC won't see it, and
it can get collected.  This patch just refactors `new_insn_send` to keep
the object on the stack

Co-authored-by: John Hawthorn <john@h...>

diff --git a/compile.c b/compile.c
index d1586ac..388d476 100644
--- a/compile.c
+++ b/compile.c
@@ -1302,12 +1302,15 @@ static INSN * https://github.com/ruby/ruby/blob/trunk/compile.c#L1302
 new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords)
 {
     VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2);
-    operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
+    VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
+    operands[0] = ci;
     operands[1] = (VALUE)blockiseq;
     if (blockiseq) {
         RB_OBJ_WRITTEN(iseq, Qundef, blockiseq);
     }
-    return new_insn_core(iseq, line_no, BIN(send), 2, operands);
+    INSN *insn = new_insn_core(iseq, line_no, BIN(send), 2, operands);
+    RB_GC_GUARD(ci);
+    return insn;
 }
 
 static rb_iseq_t *
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index daa8b5c..1f75a34 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -175,6 +175,16 @@ class TestGc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_gc.rb#L175
     assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")}
   end
 
+  def test_stress_compile_send
+    assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "")
+      GC.stress = true
+      begin
+        eval("A::B.c(1, 1, d: 234)")
+      rescue
+      end
+    EOS
+  end
+
   def test_singleton_method
     assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]")
       GC.stress = true
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]