diff --git a/hash.c b/hash.c index e8613339ba..83b9e9ce66 100644 --- a/hash.c +++ b/hash.c @@ -811,6 +811,14 @@ ar_add_direct_with_hash(VALUE hash, st_data_t key, st_data_t val, st_hash_t hash } } +static void +ensure_ar_table(VALUE hash) +{ + if (!RHASH_AR_TABLE_P(hash)) { + rb_raise(rb_eRuntimeError, "hash representation was changed during iteration"); + } +} + static int ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg) { @@ -822,6 +830,7 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i); enum st_retval retval = (*func)(pair->key, pair->val, arg, 0); + ensure_ar_table(hash); /* pair may be not valid here because of theap */ switch (retval) { @@ -896,6 +905,7 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg hint = ar_hint(hash, i); retval = (*func)(key, pair->val, arg, 0); + ensure_ar_table(hash); hash_verify(hash); switch (retval) { @@ -956,6 +966,7 @@ ar_update(VALUE hash, st_data_t key, old_key = key; retval = (*func)(&key, &value, arg, existing); /* pair can be invalid here because of theap */ + ensure_ar_table(hash); switch (retval) { case ST_CONTINUE: