summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2022-03-21 15:35:07 +0900
committernagachika <nagachika@ruby-lang.org>2022-03-21 15:35:07 +0900
commite0146e6cc8f3578b02ad5f228f86bf1aef566d16 (patch)
treef86681b0b8bf16515b59786f588ef00fdfdd6aa4 /class.c
parentf404b21f849af06fb8bbd4b87fdfb585e904d6c3 (diff)
merge revision(s) 97426e15d721119738a548ecfa7232b1d027cd34: [Backport #18627]
[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(-)
Diffstat (limited to 'class.c')
-rw-r--r--class.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/class.c b/class.c
index b607135e2f..6a4d3fb264 100644
--- a/class.c
+++ b/class.c
@@ -973,17 +973,22 @@ rb_include_module(VALUE klass, VALUE module)
int do_include = 1;
while (iclass) {
VALUE check_class = iclass->klass;
- while (check_class) {
- if (RB_TYPE_P(check_class, T_ICLASS) &&
- (RBASIC(check_class)->klass == 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) {
+ if (RB_TYPE_P(check_class, T_ICLASS) &&
+ (RBASIC(check_class)->klass == 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;
}
}
@@ -1180,17 +1185,22 @@ rb_prepend_module(VALUE klass, VALUE module)
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;
}
}