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:
parent
049913fdef
commit
bfd769a29c
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user