Fix use-after-free when clearing array during flatten

[Bug #22318]

Array#flatten triggers an use-after-free it does not account for when the
call to rb_check_array_type modifies the source array. The following script
crashes:

    a = (1..100_000).to_a
    $a = a
    bad = Object.new
    def bad.to_ary; $a.clear; [1,2,3]; end
    a << bad
    a.flatten
This commit is contained in:
Peter Zhu committed 2026-09-16 12:28:30 +09:00
1 parent 94f5f02bab
commit 5eeaedc3d3
2 files changed
+20 -2
Notes: git 2026-09-16 03:29:04 +00:00

No files matched your search

+7 -2
View File
@@ -6697,7 +6697,7 @@ static VALUE
flatten(VALUE ary, int level)
{
long i;
VALUE stack, result, tmp = 0, elt;
VALUE stack, result, tmp = Qnil, elt;
VALUE memo = Qfalse;
for (i = 0; i < RARRAY_LEN(ary); i++) {
@@ -6707,9 +6707,14 @@ flatten(VALUE ary, int level)
break;
}
}
if (i == RARRAY_LEN(ary)) {
if (NIL_P(tmp)) {
return ary;
}
if (i > RARRAY_LEN(ary)) {
/* ary was shrunk while converting an element with #to_ary, so
the scanned elements may no longer exist in ary */
i = RARRAY_LEN(ary);
}
result = ary_new(0, RARRAY_LEN(ary));
ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));