ensure that inserting into a hash causes its hash iteration order to change
authorYves Orton <demerphq@gmail.com>
Sun, 17 Mar 2013 19:48:45 +0000 (20:48 +0100)
committerYves Orton <demerphq@gmail.com>
Mon, 18 Mar 2013 23:23:12 +0000 (00:23 +0100)
This serves two functions, it makes it harder for an attacker
to learn useful information by viewing the output of keys(),
and it makes "insert during traversal" errors much easier to
spot, as they will almost always produce degenerate behavior.

hv.c

diff --git a/hv.c b/hv.c
index 3de86d1..5fc0296 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -789,8 +789,11 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
 
     /* This logic semi-randomizes the insert order in a bucket.
      * Either we insert into the top, or the slot below the top,
-     * making it harder to see if there is a collision.
+     * making it harder to see if there is a collision. We also
+     * reset the iterator randomizer if there is one.
      */
+    if (SvOOK(hv))
+        HvAUX(hv)->xhv_rand= (U32)PL_hash_rand_bits;
     PL_hash_rand_bits += (PTRV)entry ^ hash; /* we don't bother to use ptr_hash here */
     PL_hash_rand_bits= ROTL_UV(PL_hash_rand_bits,1);
     if ( !*oentry || (PL_hash_rand_bits & 1) ) {