summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2023-02-08 15:27:28 -0500
committerAaron Patterson <aaron.patterson@gmail.com>2023-02-09 11:24:32 -0800
commitb9e6580135d20cf3fff2e872b3e54c08e96468cb (patch)
tree9618a8a275d1a293d8523eb876a782a181173cf6 /class.c
parent0ddf29f4d170e90b895f4fbd313a716d770932b8 (diff)
downloadruby-b9e6580135d20cf3fff2e872b3e54c08e96468cb.tar.gz
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>
Diffstat (limited to 'class.c')
-rw-r--r--class.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/class.c b/class.c
index 333a9d78e5..cf1731c1ab 100644
--- a/class.c
+++ b/class.c
@@ -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;