diff options
author | Nicholas Clark <nick@ccl4.org> | 2021-09-27 08:20:46 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2021-10-11 11:30:25 +0000 |
commit | 0095ebd8b96d81e41d1fa374c2d31b189d2dee9e (patch) | |
tree | b9199f687c3c1193e6bab64a9e1869ac53715d91 /hv.c | |
parent | 53a41f9c2c0671d8e97b2d47afa3130fe376f322 (diff) | |
download | perl-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.c | 15 |
1 files changed, 9 insertions, 6 deletions
@@ -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; |