fix hashing of hash-table values

the order of keys+values in the table could affect the
 hash code, due to an interation with the depth-limiting
 counter
 Closes PR 10985
This commit is contained in:
Matthew Flatt 2010-06-23 06:53:04 -10:00
parent 049913fdef
commit bfd769a29c
2 changed files with 48 additions and 3 deletions

View File

@ -2346,6 +2346,47 @@
(arity-test hash-eq? 1 1)
(arity-test hash-weak? 1 1)
;; Ensure that hash-table hashing is not sensitive to the
;; order of key+value additions
(let ()
(define ht (make-hash))
(define ht2 (make-hash))
(struct a (x) #:transparent)
(define (shuffle c l)
(if (zero? c)
l
(shuffle
(sub1 c)
(let ([n (quotient (length l) 2)])
(let loop ([a (take l n)][b (drop l n)])
(cond
[(null? a) b]
[(null? b) a]
[(zero? (random 2))
(cons (car a) (loop (cdr a) b))]
[else
(cons (car b) (loop a (cdr b)))]))))))
(define l (for/list ([i (in-range 1000)])
i))
(define l2 (shuffle 7 l))
(for ([i (in-list l)])
(hash-set! ht (a i) (a (a i))))
(for ([i (in-list l2)])
(hash-set! ht2 (a i) (a (a i))))
(test (equal-hash-code ht) values (equal-hash-code ht2))
(let ([ht (for/hash ([i (in-list l)])
(values (a i) (a (a i))))]
[ht2 (for/hash ([i (in-list l2)])
(values (a i) (a (a i))))])
(test (equal-hash-code ht) values (equal-hash-code ht2))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Misc

View File

@ -1207,12 +1207,13 @@ static long equal_hash_key(Scheme_Object *o, long k, Hash_Info *hi)
Scheme_Hash_Table *ht = (Scheme_Hash_Table *)o;
Scheme_Object **vals, **keys;
int i;
long vk;
long vk, old_depth;
# include "mzhashchk.inc"
k = (k << 1) + 3;
hi->depth += 2;
old_depth = hi->depth;
keys = ht->keys;
vals = ht->vals;
@ -1223,6 +1224,7 @@ static long equal_hash_key(Scheme_Object *o, long k, Hash_Info *hi)
vk += equal_hash_key(vals[i], 0, hi);
MZ_MIX(vk);
k += vk; /* can't mix k, because the key order shouldn't matter */
hi->depth = old_depth; /* also needed to avoid order-sensitivity */
}
}
@ -1233,13 +1235,14 @@ static long equal_hash_key(Scheme_Object *o, long k, Hash_Info *hi)
Scheme_Hash_Tree *ht = (Scheme_Hash_Tree *)o;
Scheme_Object *ik, *iv;
int i;
long vk;
long vk, old_depth;
# include "mzhashchk.inc"
k = (k << 1) + 3;
hi->depth += 2;
old_depth = hi->depth;
for (i = ht->count; i--; ) {
scheme_hash_tree_index(ht, i, &ik, &iv);
vk = equal_hash_key(ik, 0, hi);
@ -1247,6 +1250,7 @@ static long equal_hash_key(Scheme_Object *o, long k, Hash_Info *hi)
vk += equal_hash_key(iv, 0, hi);
MZ_MIX(vk);
k += vk; /* can't mix k, because the key order shouldn't matter */
hi->depth = old_depth; /* also needed to avoid order-sensitivity */
}
return k;