summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2021-09-27 08:20:46 +0000
committerNicholas Clark <nick@ccl4.org>2021-10-11 11:30:25 +0000
commit0095ebd8b96d81e41d1fa374c2d31b189d2dee9e (patch)
treeb9199f687c3c1193e6bab64a9e1869ac53715d91 /hv.c
parent53a41f9c2c0671d8e97b2d47afa3130fe376f322 (diff)
downloadperl-0095ebd8b96d81e41d1fa374c2d31b189d2dee9e.tar.gz
No need to set dest->xhv_rand in S_hsplit() called from hv_common()
Perl_hv_common() only calls S_hsplit() after inserting a new hash key, if the hash meets the "split" criteria. Inserting the new hash key has already set HvAUX(hv)->xhv_rand to PL_hash_rand_bits (if the hash has an aux struct), so no need to repeat the same assignment in S_hsplit() for this case. However, this code path in S_hsplit() can also be reached from Perl_hv_ksplit() for the case of assigning to `keys %hash` for a hash which has an aux struct. The call to `keys` resets the hash iterator (in LVALUE context as well as RVALUE context), but when the assignment changed the bucket size this also had the size effect of causing a new iteration order. It's not clear whether this really matters for security of the internal hash state, but as this behaviour is both observable and can easily be retained, it seems worthwhile adding the small amount of extra code needed to keep it. Hence this commit is (or is intended to be) a pure refactoring, without any observable behaviour change.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/hv.c b/hv.c
index f4f804aa0c..956e805b5f 100644
--- a/hv.c
+++ b/hv.c
@@ -1469,12 +1469,7 @@ S_hsplit(pTHX_ HV *hv, STRLEN const oldsize, STRLEN newsize)
* or have been allocated by us*/
if (do_aux) {
struct xpvhv_aux *const dest = HvAUX(hv);
- if (SvOOK(hv)) {
- /* we reset the iterator's xhv_rand as well, so they get a totally new ordering */
-#ifdef PERL_HASH_RANDOMIZE_KEYS
- dest->xhv_rand = (U32)PL_hash_rand_bits;
-#endif
- } else {
+ if (!SvOOK(hv)) {
/* no existing aux structure, but we allocated space for one
* so initialize it properly. This unrolls hv_auxinit() a bit,
* since we have to do the realloc anyway. */
@@ -1576,7 +1571,15 @@ Perl_hv_ksplit(pTHX_ HV *hv, IV newmax)
a = (char *) HvARRAY(hv);
if (a) {
+#ifdef PERL_HASH_RANDOMIZE_KEYS
+ U32 was_ook = SvOOK(hv);
+#endif
hsplit(hv, oldsize, newsize);
+#ifdef PERL_HASH_RANDOMIZE_KEYS
+ if (was_ook && SvOOK(hv) && HvTOTALKEYS(hv)) {
+ HvAUX(hv)->xhv_rand = (U32)PL_hash_rand_bits;
+ }
+#endif
} else {
Newxz(a, PERL_HV_ARRAY_ALLOC_BYTES(newsize), char);
xhv->xhv_max = newsize - 1;