From ab249864cc2cfc64f89244e07b62cda79a73a687 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 25 Mar 2026 15:24:01 +0900 Subject: [PATCH] gc.c: remove all matching entries in mrb_gc_unregister() Previously only the first match was removed, leaking duplicate entries when the same object was registered multiple times. Use two-pointer compaction for O(N) removal. Fixes #6760. Co-authored-by: Claude --- src/gc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gc.c b/src/gc.c index 411cb6852..37bb04e06 100644 --- a/src/gc.c +++ b/src/gc.c @@ -541,15 +541,15 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) if (!mrb_array_p(table)) return; struct RArray *a = mrb_ary_ptr(table); mrb_ary_modify(mrb, a); - mrb_int len = ARY_LEN(a)-1; + mrb_int len = ARY_LEN(a); mrb_value *ptr = ARY_PTR(a); - for (mrb_int i = 0; i <= len; i++) { - if (mrb_ptr(ptr[i]) == mrb_ptr(obj)) { - ARY_SET_LEN(a, len); - memmove(&ptr[i], &ptr[i + 1], (len - i) * sizeof(mrb_value)); - break; + mrb_int w = 0; + for (mrb_int r = 0; r < len; r++) { + if (mrb_ptr(ptr[r]) != mrb_ptr(obj)) { + ptr[w++] = ptr[r]; } } + ARY_SET_LEN(a, w); } MRB_API struct RBasic*