summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-05-21 18:33:56 -0700
committerGitHub <noreply@github.com>2021-05-21 18:33:56 -0700
commit8b00bfb7c2c33827490c78a16c44b102cb0d724b (patch)
treee8d06af25bd9504cf4984002f4bffaac42a777c8 /array.c
parentb2fc592c3046e60fdfbb5692d52cc7cbf814b6d0 (diff)
Do not allow array modifications after freeze inside sort!
If freezing an array inside sort!, previously the array could be modified after the freeze. This checks whether the receiver is frozen after every yield and potential call to #> or #<, preventing modifications if the receiver is frozen inside the block or by the #> or #< call. Fixes [Bug #17739]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4335 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'array.c')
-rw-r--r--array.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/array.c b/array.c
index 881270b915..83e4d186bd 100644
--- a/array.c
+++ b/array.c
@@ -3213,6 +3213,7 @@ rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
struct ary_sort_data {
VALUE ary;
+ VALUE receiver;
struct cmp_opt_data cmp_opt;
};
@@ -3225,6 +3226,15 @@ sort_reentered(VALUE ary)
return Qnil;
}
+static void
+sort_returned(struct ary_sort_data *data)
+{
+ if (rb_obj_frozen_p(data->receiver)) {
+ rb_raise(rb_eFrozenError, "array frozen during sort");
+ }
+ sort_reentered(data->ary);
+}
+
static int
sort_1(const void *ap, const void *bp, void *dummy)
{
@@ -3238,7 +3248,7 @@ sort_1(const void *ap, const void *bp, void *dummy)
args[1] = b;
retval = rb_yield_values2(2, args);
n = rb_cmpint(retval, a, b);
- sort_reentered(data->ary);
+ sort_returned(data);
return n;
}
@@ -3264,7 +3274,7 @@ sort_2(const void *ap, const void *bp, void *dummy)
retval = rb_funcallv(a, id_cmp, 1, &b);
n = rb_cmpint(retval, a, b);
- sort_reentered(data->ary);
+ sort_returned(data);
return n;
}
@@ -3316,6 +3326,7 @@ rb_ary_sort_bang(VALUE ary)
long len = RARRAY_LEN(ary);
RBASIC_CLEAR_CLASS(tmp);
data.ary = tmp;
+ data.receiver = ary;
data.cmp_opt.opt_methods = 0;
data.cmp_opt.opt_inited = 0;
RARRAY_PTR_USE(tmp, ptr, {