aboutsummaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorJean Boussier <byroot@ruby-lang.org>2023-04-11 10:55:46 +0200
committerJean Boussier <jean.boussier@gmail.com>2023-04-11 16:56:14 +0200
commit8c360ce713f57d4177de833297364f6f6d950420 (patch)
treedf98faaf72d599ca733fec57198c66047f62c45f /hash.c
parent7b230bc8486e7d451113c3c0301adcecfc09b893 (diff)
downloadruby-8c360ce713f57d4177de833297364f6f6d950420.tar.gz
hash.c: Fix hash_iter_lev_dec corrupting shape
[Bug #19589] When decrementing `iter_lev` from `65` to `64` the flags would be corrupted, causing the shape_id to be invalid.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/hash.c b/hash.c
index fc214cce54..32c660a210 100644
--- a/hash.c
+++ b/hash.c
@@ -1367,13 +1367,19 @@ iter_lev_in_ivar_set(VALUE hash, int lev)
rb_ivar_set_internal(hash, id_hash_iter_lev, INT2FIX(lev));
}
-static int
+static inline int
iter_lev_in_flags(VALUE hash)
{
unsigned int u = (unsigned int)((RBASIC(hash)->flags >> RHASH_LEV_SHIFT) & RHASH_LEV_MAX);
return (int)u;
}
+static inline void
+iter_lev_in_flags_set(VALUE hash, int lev)
+{
+ RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
+}
+
static int
RHASH_ITER_LEV(VALUE hash)
{
@@ -1397,7 +1403,7 @@ hash_iter_lev_inc(VALUE hash)
}
else {
lev += 1;
- RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
+ iter_lev_in_flags_set(hash, lev);
if (lev == RHASH_LEV_MAX) {
iter_lev_in_ivar_set(hash, lev);
}
@@ -1415,7 +1421,7 @@ hash_iter_lev_dec(VALUE hash)
}
else {
HASH_ASSERT(lev > 0);
- RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((lev-1) << RHASH_LEV_SHIFT));
+ iter_lev_in_flags_set(hash, lev - 1);
}
}