diff options
author | Yusuke Endoh <mame@ruby-lang.org> | 2023-11-08 17:09:33 +0900 |
---|---|---|
committer | Yusuke Endoh <mame@ruby-lang.org> | 2023-11-21 15:15:23 +0900 |
commit | a787e0d6494443cfd9bd05ac746704079dcfd03f (patch) | |
tree | fe4769153f7e52dcd20dc13556dc1511c31b8a22 /hash.c | |
parent | c3ab946e86134e05a81c0587ef1d5cdf1de4492f (diff) |
Raise an exception if ar_table is converted to st_table during iteration
ar_table may be converted to st_table by `ar_force_convert_table`.
If the conversion occurs during the iteration of ar_table, the iteration
may lead to memory corruption.
This change prevents the catastrophy by throwing an exception when the
conversion is detected.
This issue is reported by [SuperS](https://hackerone.com/superss)
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 11 |
1 files changed, 11 insertions, 0 deletions
@@ -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: |