From 24fe22a5da21c9df8584a4ce6b6d1ce18ac41cc2 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Fri, 17 Nov 2023 17:57:25 -0500 Subject: [PATCH] Fix ordering for auto compaction in get_overloaded_cme() Found through GC.stress + GC.auto_compact crashes in GH-8932. Previously, the compaction run within `rb_method_entry_alloc()` could move the `def->body.iseq.cref` and `iseqptr` set up before the call and leave the `def` pointing to moved addresses. Nothing was marking `def` during that GC run. Low probability reproducer: GC.stress = true GC.auto_compact = true arr = [] alloc = 1000.times.map { [] } alloc = nil a = arr.first GC.start --- vm_method.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vm_method.c b/vm_method.c index d2b642e6e1..245c58ac3e 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1033,15 +1033,15 @@ get_overloaded_cme(const rb_callable_method_entry_t *cme) else { // create rb_method_definition_t *def = rb_method_definition_create(VM_METHOD_TYPE_ISEQ, cme->def->original_id); - def->body.iseq.cref = cme->def->body.iseq.cref; - def->body.iseq.iseqptr = ISEQ_BODY(cme->def->body.iseq.iseqptr)->mandatory_only_iseq; - rb_method_entry_t *me = rb_method_entry_alloc(cme->called_id, cme->owner, cme->defined_class, def, false); + RB_OBJ_WRITE(me, &def->body.iseq.cref, cme->def->body.iseq.cref); + RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, ISEQ_BODY(cme->def->body.iseq.iseqptr)->mandatory_only_iseq); + ASSERT_vm_locking(); st_insert(overloaded_cme_table(), (st_data_t)cme, (st_data_t)me);