mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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.
This commit is contained in:
+11
-7
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user