From 752ebe6b7f0ad24f3841602f6b21ec5b808c66c5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 21 Aug 2024 18:31:46 +0900 Subject: [PATCH] array.c (mrb_ary_sort_bang): check if array is modified in blocks This address at least part of #6326. CRuby copied the array internally, but mruby avoid copying to reserve memory. --- src/array.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/array.c b/src/array.c index 111e9f44e..681917f5d 100644 --- a/src/array.c +++ b/src/array.c @@ -1583,7 +1583,7 @@ mrb_ary_delete(mrb_state *mrb, mrb_value self) } static mrb_bool -sort_cmp(mrb_state *mrb, mrb_value *p, mrb_int a, mrb_int b, mrb_value blk) +sort_cmp(mrb_state *mrb, mrb_value ary, mrb_value *p, mrb_int a, mrb_int b, mrb_value blk) { mrb_int cmp; @@ -1592,6 +1592,10 @@ sort_cmp(mrb_state *mrb, mrb_value *p, mrb_int a, mrb_int b, mrb_value blk) } else { mrb_value c = mrb_funcall_id(mrb, blk, MRB_SYM(call), 2, p[a], p[b]); + mrb_int size = RARRAY_LEN(ary); + if (RARRAY_PTR(ary) != p || size < a || size < b) { + mrb_raise(mrb, E_RUNTIME_ERROR, "array modified during sort"); + } if (mrb_nil_p(c) || !mrb_fixnum_p(c)) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %!v and %!v failed", p[a], p[b]); } @@ -1601,22 +1605,22 @@ sort_cmp(mrb_state *mrb, mrb_value *p, mrb_int a, mrb_int b, mrb_value blk) } static void -heapify(mrb_state *mrb, mrb_value *a, mrb_int index, mrb_int size, mrb_value blk) +heapify(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int index, mrb_int size, mrb_value blk) { mrb_int max = index; mrb_int left_index = 2 * index + 1; mrb_int right_index = left_index + 1; - if (left_index < size && sort_cmp(mrb, a, left_index, max, blk)) { + if (left_index < size && sort_cmp(mrb, ary, a, left_index, max, blk)) { max = left_index; } - if (right_index < size && sort_cmp(mrb, a, right_index, max, blk)) { + if (right_index < size && sort_cmp(mrb, ary, a, right_index, max, blk)) { max = right_index; } if (max != index) { mrb_value tmp = a[max]; a[max] = a[index]; a[index] = tmp; - heapify(mrb, a, max, size, blk); + heapify(mrb, ary, a, max, size, blk); } } @@ -1641,13 +1645,13 @@ mrb_ary_sort_bang(mrb_state *mrb, mrb_value ary) mrb_value *a = RARRAY_PTR(ary); for (mrb_int i = n / 2 - 1; i > -1; i--) { - heapify(mrb, a, i, n, blk); + heapify(mrb, ary, a, i, n, blk); } for (mrb_int i = n - 1; i > 0; i--) { mrb_value tmp = a[0]; a[0] = a[i]; a[i] = tmp; - heapify(mrb, a, 0, i, blk); + heapify(mrb, ary, a, 0, i, blk); } return ary; }