mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Fix out-of-bounds in Array#sample when array modified
The call to rand (through RAND_UPTO) or to_int (through NUM2LONG) can run
aribtrary Ruby code, which can modify the source array. The size of the
array may shrink, which could cause an out-of-bounds read on the array.
We do check again that all the random numbers are within the new array
size, but the check is incorrect because it checks against len but should
check against len-i (which is the random number requested). The following
script will sometimes crash and other times output corrupted results:
ary = (1..1_000).to_a
obj = Object.new
obj.define_singleton_method(:to_int) do
ary.replace((1..50).to_a)
10
end
gen = Object.new
def gen.rand(lim) = 49
p ary.sample(obj, random: gen)
For example, it can output:
[50, nil, nil, nil, nil, nil, nil, 367219703829, 40, 13294122074]
This commit is contained in:
1 parent
22fda5cc52
commit
11f57c63e7
2 files changed
+14
-1
Notes:
git
2026-09-17 07:27:01 +00:00
No files matched your search
@@ -7008,7 +7008,7 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
|
||||
len = RARRAY_LEN(ary);
|
||||
if (len < k && n <= numberof(idx)) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (rnds[i] >= len) return rb_ary_new_capa(0);
|
||||
if (rnds[i] >= len - 1) return rb_ary_new_capa(0);
|
||||
}
|
||||
}
|
||||
if (n > len) n = len;
|
||||
|
||||
@@ -3367,6 +3367,19 @@ class TestArray < Test::Unit::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
def test_sample_modify_array_out_of_bounds
|
||||
ary = (1..1_000).to_a
|
||||
obj = Object.new
|
||||
obj.define_singleton_method(:to_int) do
|
||||
ary.replace((1..50).to_a)
|
||||
10
|
||||
end
|
||||
gen = Object.new
|
||||
# 49 will be out-of-bounds when ary.replace is called
|
||||
def gen.rand(lim) = 49
|
||||
assert_equal([], ary.sample(obj, random: gen))
|
||||
end
|
||||
|
||||
def test_cycle
|
||||
a = []
|
||||
[0, 1, 2].cycle do |i|
|
||||
|
||||
Reference in new issue
Block a user