[Bug #21331] Prohibit hash modification during stlike loop
This commit is contained in:
parent
7f5b4fb26e
commit
7793b59c8d
Notes:
git
2025-05-14 02:42:50 +00:00
20
hash.c
20
hash.c
@ -1404,6 +1404,7 @@ hash_foreach_ensure(VALUE hash)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This does not manage iteration level */
|
||||||
int
|
int
|
||||||
rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
|
rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
|
||||||
{
|
{
|
||||||
@ -1415,6 +1416,7 @@ rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This does not manage iteration level */
|
||||||
int
|
int
|
||||||
rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
|
rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
|
||||||
{
|
{
|
||||||
@ -3486,6 +3488,20 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
|
|||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
transform_values_call(VALUE hash)
|
||||||
|
{
|
||||||
|
rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
transform_values(VALUE hash)
|
||||||
|
{
|
||||||
|
hash_iter_lev_inc(hash);
|
||||||
|
rb_ensure(transform_values_call, hash, hash_foreach_ensure, hash);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* transform_values {|value| ... } -> new_hash
|
* transform_values {|value| ... } -> new_hash
|
||||||
@ -3514,7 +3530,7 @@ rb_hash_transform_values(VALUE hash)
|
|||||||
SET_DEFAULT(result, Qnil);
|
SET_DEFAULT(result, Qnil);
|
||||||
|
|
||||||
if (!RHASH_EMPTY_P(hash)) {
|
if (!RHASH_EMPTY_P(hash)) {
|
||||||
rb_hash_stlike_foreach_with_replace(result, transform_values_foreach_func, transform_values_foreach_replace, result);
|
transform_values(result);
|
||||||
compact_after_delete(result);
|
compact_after_delete(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3549,7 +3565,7 @@ rb_hash_transform_values_bang(VALUE hash)
|
|||||||
rb_hash_modify_check(hash);
|
rb_hash_modify_check(hash);
|
||||||
|
|
||||||
if (!RHASH_TABLE_EMPTY_P(hash)) {
|
if (!RHASH_TABLE_EMPTY_P(hash)) {
|
||||||
rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
|
transform_values(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
|
@ -1853,6 +1853,14 @@ class TestHash < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
|
assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
|
||||||
|
|
||||||
|
x = (1..1337).to_h {|k| [k, k]}
|
||||||
|
assert_raise_with_message(RuntimeError, /rehash during iteration/) do
|
||||||
|
x.transform_values! {|v|
|
||||||
|
x.rehash if v == 1337
|
||||||
|
v * 2
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def hrec h, n, &b
|
def hrec h, n, &b
|
||||||
|
Loading…
x
Reference in New Issue
Block a user