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

ruby-changes:71458

From: Peter <ko1@a...>
Date: Fri, 18 Mar 2022 22:19:34 +0900 (JST)
Subject: [ruby-changes:71458] 97426e15d7 (master): [Bug #18627] Fix crash when including module

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

From 97426e15d721119738a548ecfa7232b1d027cd34 Mon Sep 17 00:00:00 2001
From: Peter Zhu <peter@p...>
Date: Wed, 16 Mar 2022 15:46:40 -0400
Subject: [Bug #18627] Fix crash when including module

During lazy sweeping, the iclass could be a dead object that has not yet
been swept. However, the chain of superclasses of the iclass could
already have been swept (and become a new object), which would cause a
crash when trying to read the object.
---
 class.c | 48 ++++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/class.c b/class.c
index 572275f5ce..9988b080d9 100644
--- a/class.c
+++ b/class.c
@@ -1117,17 +1117,24 @@ rb_include_module(VALUE klass, VALUE module) https://github.com/ruby/ruby/blob/trunk/class.c#L1117
         int do_include = 1;
         while (iclass) {
             VALUE check_class = iclass->klass;
-            while (check_class) {
-                if (RB_TYPE_P(check_class, T_ICLASS) &&
-                        (METACLASS_OF(check_class) == module)) {
-                    do_include = 0;
+            /* During lazy sweeping, iclass->klass could be a dead object that
+             * has not yet been swept. */
+            if (!rb_objspace_garbage_object_p(check_class)) {
+                while (check_class) {
+                    RUBY_ASSERT(!rb_objspace_garbage_object_p(check_class));
+
+                    if (RB_TYPE_P(check_class, T_ICLASS) &&
+                            (METACLASS_OF(check_class) == module)) {
+                        do_include = 0;
+                    }
+                    check_class = RCLASS_SUPER(check_class);
                 }
-                check_class = RCLASS_SUPER(check_class);
-            }
 
-            if (do_include) {
-                include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE);
+                if (do_include) {
+                    include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE);
+                }
             }
+
             iclass = iclass->next;
         }
     }
@@ -1363,17 +1370,22 @@ rb_prepend_module(VALUE klass, VALUE module) https://github.com/ruby/ruby/blob/trunk/class.c#L1370
         struct rb_id_table *klass_m_tbl = RCLASS_M_TBL(klass);
         struct rb_id_table *klass_origin_m_tbl = RCLASS_M_TBL(klass_origin);
         while (iclass) {
-            if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
-                // backfill an origin iclass to handle refinements and future prepends
-                rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass);
-                RCLASS_M_TBL(iclass->klass) = klass_m_tbl;
-                VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass));
-                RCLASS_SET_SUPER(iclass->klass, origin);
-                RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass));
-                RCLASS_SET_ORIGIN(iclass->klass, origin);
-                RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
+            /* During lazy sweeping, iclass->klass could be a dead object that
+             * has not yet been swept. */
+            if (!rb_objspace_garbage_object_p(iclass->klass)) {
+                if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
+                    // backfill an origin iclass to handle refinements and future prepends
+                    rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass);
+                    RCLASS_M_TBL(iclass->klass) = klass_m_tbl;
+                    VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass));
+                    RCLASS_SET_SUPER(iclass->klass, origin);
+                    RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass));
+                    RCLASS_SET_ORIGIN(iclass->klass, origin);
+                    RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
+                }
+                include_modules_at(iclass->klass, iclass->klass, module, FALSE);
             }
-            include_modules_at(iclass->klass, iclass->klass, module, FALSE);
+
             iclass = iclass->next;
         }
     }
-- 
cgit v1.2.1


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

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