From bbf7c43c371b26b99e75a881d29f3e50d160f188 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Apr 2026 08:59:07 +0900 Subject: [PATCH] array.c: restore arena around heap sort per-call protections heapify() and heap_delete_root() call mrb_gc_protect() to guard a C-local mrb_value across potential GC points inside sort_cmp(). They were missing the matching mrb_gc_arena_save/restore pair, so each call leaked one arena slot. For O(n log n) heapify calls under MRB_GC_FIXED_ARENA this overflows the 100-slot arena and raises NoMemoryError, e.g. during Array#repeated_permutation tests. Wrap each function body with mrb_gc_arena_save/restore, matching the pattern already used in insertion_sort() above. Co-authored-by: Claude --- src/array.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/array.c b/src/array.c index 5e9a6a90a..dab869645 100644 --- a/src/array.c +++ b/src/array.c @@ -2290,6 +2290,7 @@ sort_cmp(mrb_state *mrb, mrb_value ary, mrb_value a_val, mrb_value b_val, mrb_va static void heapify(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int index, mrb_int size, mrb_value blk) { + int ai = mrb_gc_arena_save(mrb); mrb_value val = a[index]; /* save root to hole */ mrb_gc_protect(mrb, val); @@ -2308,6 +2309,7 @@ heapify(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int index, mrb_int size index = child; } a[index] = val; /* place saved value */ + mrb_gc_arena_restore(mrb, ai); } /* Floyd's bottom-up heap deletion: sift the hole down to a leaf without @@ -2317,6 +2319,7 @@ heapify(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int index, mrb_int size static void heap_delete_root(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int size, mrb_value blk) { + int ai = mrb_gc_arena_save(mrb); /* a[0] already holds the value to be re-inserted (set by caller) */ mrb_value last = a[0]; mrb_gc_protect(mrb, last); @@ -2347,6 +2350,7 @@ heap_delete_root(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int size, mrb_ hole = parent; } a[hole] = last; + mrb_gc_arena_restore(mrb, ai); } static void