diff options
author | eileencodes <eileencodes@gmail.com> | 2023-02-08 15:27:28 -0500 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2023-02-09 11:24:32 -0800 |
commit | b9e6580135d20cf3fff2e872b3e54c08e96468cb (patch) | |
tree | 9618a8a275d1a293d8523eb876a782a181173cf6 /class.c | |
parent | 0ddf29f4d170e90b895f4fbd313a716d770932b8 (diff) |
Copy cvar table on clone
When a class with a class variable is cloned we need to also copy the
cvar cache table from the original table to the clone. I found this bug
while working on fixing [Bug #19379]. While this does not fix that bug
directly it is still a required change to fix another bug revealed by
the fix in https://github.com/ruby/ruby/pull/7265
This needs to be backported to 3.2.x and 3.1.x.
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7275
Diffstat (limited to 'class.c')
-rw-r--r-- | class.c | 31 |
1 files changed, 31 insertions, 0 deletions
@@ -404,6 +404,27 @@ class_init_copy_check(VALUE clone, VALUE orig) } } +struct cvc_table_copy_ctx { + VALUE clone; + struct rb_id_table * new_table; +}; + +static enum rb_id_table_iterator_result +cvc_table_copy(ID id, VALUE val, void *data) { + struct cvc_table_copy_ctx *ctx = (struct cvc_table_copy_ctx *)data; + struct rb_cvar_class_tbl_entry * orig_entry; + orig_entry = (struct rb_cvar_class_tbl_entry *)val; + + struct rb_cvar_class_tbl_entry *ent; + + ent = ALLOC(struct rb_cvar_class_tbl_entry); + ent->class_value = ctx->clone; + ent->global_cvar_state = orig_entry->global_cvar_state; + rb_id_table_insert(ctx->new_table, id, (VALUE)ent); + + return ID_TABLE_CONTINUE; +} + static void copy_tables(VALUE clone, VALUE orig) { @@ -411,6 +432,16 @@ copy_tables(VALUE clone, VALUE orig) rb_free_const_table(RCLASS_CONST_TBL(clone)); RCLASS_CONST_TBL(clone) = 0; } + if (RCLASS_CVC_TBL(orig)) { + struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(orig); + struct rb_id_table *rb_cvc_tbl_dup = rb_id_table_create(rb_id_table_size(rb_cvc_tbl)); + + struct cvc_table_copy_ctx ctx; + ctx.clone = clone; + ctx.new_table = rb_cvc_tbl_dup; + rb_id_table_foreach(rb_cvc_tbl, cvc_table_copy, &ctx); + RCLASS_CVC_TBL(clone) = rb_cvc_tbl_dup; + } RCLASS_M_TBL(clone) = 0; if (!RB_TYPE_P(clone, T_ICLASS)) { st_data_t id; |