@@ -455,6 +455,12 @@ ary_subtract_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_va
455455mrb_value result = mrb_ary_new(mrb);
456456457457if (total_len > SET_OP_HASH_THRESHOLD) {
458+/* Create shared copies to protect elements during khash operations */
459+mrb_value *argv_copies = (mrb_value *)mrb_alloca(mrb, sizeof(mrb_value) * argc);
460+for (mrb_int i = 0; i < argc; i++) {
461+argv_copies[i] = mrb_ary_make_shared_copy(mrb, argv[i]);
462+ }
463+458464ary_set_t set_struct;
459465ary_set_t *set = &set_struct;
460466ary_init_temp_set(mrb, set, total_len);
@@ -465,7 +471,7 @@ ary_subtract_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_va
465471MRB_TRY(&c_jmp) {
466472mrb->jmp = &c_jmp;
467473for (mrb_int i = 0; i < argc; i++) {
468-ary_populate_temp_set(mrb, set, argv[i]);
474+ary_populate_temp_set(mrb, set, argv_copies[i]);
469475 }
470476471477for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
@@ -568,6 +574,13 @@ ary_union_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_value
568574mrb_value result = mrb_ary_new(mrb);
569575570576if (total_len > SET_OP_HASH_THRESHOLD) {
577+/* Create shared copies to protect elements during khash operations */
578+mrb_value self_copy = mrb_ary_make_shared_copy(mrb, self);
579+mrb_value *argv_copies = (mrb_value *)mrb_alloca(mrb, sizeof(mrb_value) * argc);
580+for (mrb_int i = 0; i < argc; i++) {
581+argv_copies[i] = mrb_ary_make_shared_copy(mrb, argv[i]);
582+ }
583+571584ary_set_t set_struct;
572585ary_set_t *set = &set_struct;
573586ary_init_temp_set(mrb, set, total_len);
@@ -578,8 +591,8 @@ ary_union_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_value
578591MRB_TRY(&c_jmp) {
579592mrb->jmp = &c_jmp;
580593/* Add unique elements from self */
581-for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
582-mrb_value elem = RARRAY_PTR(self)[i];
594+for (mrb_int i = 0; i < RARRAY_LEN(self_copy); i++) {
595+mrb_value elem = RARRAY_PTR(self_copy)[i];
583596khiter_t k = kh_get(ary_set, mrb, set, elem);
584597if (kh_is_end(set, k)) {
585598kh_put(ary_set, mrb, set, elem);
@@ -589,7 +602,7 @@ ary_union_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_value
589602590603/* Add unique elements from others */
591604for (mrb_int i = 0; i < argc; i++) {
592-mrb_value other = argv[i];
605+mrb_value other = argv_copies[i];
593606for (mrb_int j = 0; j < RARRAY_LEN(other); j++) {
594607mrb_value elem = RARRAY_PTR(other)[j];
595608khiter_t k = kh_get(ary_set, mrb, set, elem);
@@ -681,6 +694,12 @@ ary_intersection_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mr
681694mrb_value result = mrb_ary_new(mrb);
682695683696if (total_len > SET_OP_HASH_THRESHOLD) {
697+/* Create shared copies to protect elements during khash operations */
698+mrb_value *argv_copies = (mrb_value *)mrb_alloca(mrb, sizeof(mrb_value) * argc);
699+for (mrb_int i = 0; i < argc; i++) {
700+argv_copies[i] = mrb_ary_make_shared_copy(mrb, argv[i]);
701+ }
702+684703ary_set_t set_struct;
685704ary_set_t *set = &set_struct;
686705ary_init_temp_set(mrb, set, total_len);
@@ -691,7 +710,7 @@ ary_intersection_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mr
691710MRB_TRY(&c_jmp) {
692711mrb->jmp = &c_jmp;
693712for (mrb_int i = 0; i < argc; i++) {
694-ary_populate_temp_set(mrb, set, argv[i]);
713+ary_populate_temp_set(mrb, set, argv_copies[i]);
695714 }
696715697716for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
@@ -824,17 +843,19 @@ ary_intersect_p(mrb_state *mrb, mrb_value self)
824843 }
825844826845if (RARRAY_LEN(shorter_ary) > SET_OP_HASH_THRESHOLD) {
846+mrb_value shorter_ary_copy = mrb_ary_make_shared_copy(mrb, shorter_ary);
847+827848ary_set_t set_struct;
828849ary_set_t *set = &set_struct;
829-ary_init_temp_set(mrb, set, RARRAY_LEN(shorter_ary));
850+ary_init_temp_set(mrb, set, RARRAY_LEN(shorter_ary_copy));
830851831852struct mrb_jmpbuf *prev_jmp = mrb->jmp;
832853struct mrb_jmpbuf c_jmp;
833854mrb_bool found = FALSE;
834855835856MRB_TRY(&c_jmp) {
836857mrb->jmp = &c_jmp;
837-ary_populate_temp_set(mrb, set, shorter_ary);
858+ary_populate_temp_set(mrb, set, shorter_ary_copy);
838859839860for (mrb_int i = 0; i < RARRAY_LEN(longer_ary); i++) {
840861khiter_t k = kh_get(ary_set, mrb, set, RARRAY_PTR(longer_ary)[i]);
@@ -1019,6 +1040,9 @@ ary_uniq_bang(mrb_state *mrb, mrb_value self)
10191040mrb_int write_pos = 0;
1020104110211042if (len > SET_OP_HASH_THRESHOLD) {
1043+/* Create shared copy to protect elements during khash operations */
1044+mrb_value self_copy = mrb_ary_make_shared_copy(mrb, self);
1045+10221046ary_set_t set_struct;
10231047ary_set_t *set = &set_struct;
10241048ary_init_temp_set(mrb, set, len);
@@ -1028,7 +1052,7 @@ ary_uniq_bang(mrb_state *mrb, mrb_value self)
1028105210291053MRB_TRY(&c_jmp) {
10301054mrb->jmp = &c_jmp;
1031-ary_populate_temp_set(mrb, set, self);
1055+ary_populate_temp_set(mrb, set, self_copy);
1032105610331057for (mrb_int read_pos = 0; read_pos < len; read_pos++) {
10341058mrb_value elem = RARRAY_PTR(self)[read_pos];