Handle mutating of array passed to Set.new during iteration
This avoids a heap-use-after-free. Fixes [Bug #21306]
This commit is contained in:
parent
be665cf855
commit
21035c826d
Notes:
git
2025-05-03 19:11:32 +00:00
19
set.c
19
set.c
@ -494,18 +494,13 @@ set_i_initialize(int argc, VALUE *argv, VALUE set)
|
|||||||
|
|
||||||
if (argc > 0 && (other = argv[0]) != Qnil) {
|
if (argc > 0 && (other = argv[0]) != Qnil) {
|
||||||
if (RB_TYPE_P(other, T_ARRAY)) {
|
if (RB_TYPE_P(other, T_ARRAY)) {
|
||||||
long len = RARRAY_LEN(other);
|
long i;
|
||||||
if (RARRAY_LEN(other) != 0) {
|
int block_given = rb_block_given_p();
|
||||||
set_table *into = RSET_TABLE(set);
|
set_table *into = RSET_TABLE(set);
|
||||||
VALUE key;
|
for (i=0; i<RARRAY_LEN(other); i++) {
|
||||||
int block_given = rb_block_given_p();
|
VALUE key = RARRAY_AREF(other, i);
|
||||||
RARRAY_PTR_USE(other, ptr, {
|
if (block_given) key = rb_yield(key);
|
||||||
for(; len > 0; len--, ptr++) {
|
set_table_insert_wb(into, set, key, NULL);
|
||||||
key = *ptr;
|
|
||||||
if (block_given) key = rb_yield(key);
|
|
||||||
set_table_insert_wb(into, set, key, NULL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -643,6 +643,11 @@ class TC_Set < Test::Unit::TestCase
|
|||||||
assert_equal([o], Set.new.merge(a).to_a)
|
assert_equal([o], Set.new.merge(a).to_a)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_initialize_mutating_array_bug_21306
|
||||||
|
a = (1..100).to_a
|
||||||
|
assert_equal(Set[0], Set.new(a){a.clear; 0})
|
||||||
|
end
|
||||||
|
|
||||||
def test_subtract
|
def test_subtract
|
||||||
set = Set[1,2,3]
|
set = Set[1,2,3]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user