diff --git a/manual/Unit srfi-69 b/manual/Unit srfi-69
index 92db700..9db2a97 100644
--- a/manual/Unit srfi-69
+++ b/manual/Unit srfi-69
@@ -13,7 +13,7 @@ CHICKEN implements SRFI 69 with SRFI 90 extensions. For more information, see
==== make-hash-table
-(make-hash-table [TEST HASH SIZE] [#:test TEST] [#:hash HASH] [#:size SIZE] [#:initial INITIAL] [#:min-load MIN-LOAD] [#:max-load MAX-LOAD] [#:weak-keys WEAK-KEYS] [#:weak-values WEAK-VALUES])
+(make-hash-table [TEST HASH SIZE] [#:test TEST] [#:hash HASH] [#:size SIZE] [#:initial INITIAL] [#:randomization RANDOMIZATION] [#:min-load MIN-LOAD] [#:max-load MAX-LOAD] [#:weak-keys WEAK-KEYS] [#:weak-values WEAK-VALUES])
Returns a new {{HASH-TABLE}} with the supplied configuration.
@@ -21,6 +21,7 @@ Returns a new {{HASH-TABLE}} with the supplied configuration.
; {{HASH}} : The hash function.
; {{SIZE}} : The expected number of table elements.
; {{INITIAL}} : The default initial value.
+; {{RANDOMIZATION}} : A value for perturbing hash values. Should never be a fixed value!
; {{MIN-LOAD}} : The minimum load factor. A {{flonum}} in (0.0 1.0).
; {{MAX-LOAD}} : The maximum load factor. A {{flonum}} in (0.0 1.0).
; {{WEAK-KEYS}} : Use weak references for keys. (Ignored)
@@ -29,7 +30,7 @@ Returns a new {{HASH-TABLE}} with the supplied configuration.
==== alist->hash-table
-(alist->hash-table A-LIST [#:test TEST] [#:hash HASH] [#:size SIZE] [#:initial INITIAL] [#:min-load MIN-LOAD] [#:max-load MAX-LOAD] [#:weak-keys WEAK-KEYS] [#:weak-values WEAK-VALUES])
+(alist->hash-table A-LIST [#:test TEST] [#:hash HASH] [#:size SIZE] [#:initial INITIAL] [#:randomization RANDOMIZATION] [#:min-load MIN-LOAD] [#:max-load MAX-LOAD] [#:weak-keys WEAK-KEYS] [#:weak-values WEAK-VALUES])
Returns a new {{HASH-TABLE}}. The {{HASH-TABLE}} is populated from the
{{A-LIST}}. The keyword arguments are per {{make-hash-table}}.
@@ -104,6 +105,13 @@ Does the {{HASH-TABLE}} have a default initial value?
The {{HASH-TABLE}} default initial value.
+==== hash-table-randomization
+
+(hash-table-randomization HASH-TABLE)
+
+The randomization number for {{HASH-TABLE}}. Make sure you never
+expose this to a potential attacker.
+
==== hash-table-keys
@@ -285,38 +293,46 @@ entry.
All hash functions return a {{fixnum}} in the range [0 {{BOUND}}).
+When given the fixnum RANDOMIZATION, these functions will use this
+to perturb the value; if not specified, the value will differ for
+each invocation of your program. This is for security reasons; an
+attacker who knows what a value hashes to can deliberately try to
+cause collisions, thereby flattening your hash table, effectively
+reducing it to a list. Always make sure you don't expose any
+hashed value to an attacker.
+
==== number-hash
-(number-hash NUMBER [BOUND])
+(number-hash NUMBER [BOUND RANDOMIZATION])
For use with {{=}} as a {{hash-table-equivalence-function}}.
==== object-uid-hash
-(object-uid-hash OBJECT [BOUND])
+(object-uid-hash OBJECT [BOUND RANDOMIZATION])
Currently a synonym for {{equal?-hash}}.
==== symbol-hash
-(symbol-hash SYMBOL [BOUND])
+(symbol-hash SYMBOL [BOUND RANDOMIZATION])
For use with {{eq?}} as a {{hash-table-equivalence-function}}.
==== keyword-hash
-(keyword-hash KEYWORD [BOUND])
+(keyword-hash KEYWORD [BOUND RANDOMIZATION])
For use with {{eq?}} as a {{hash-table-equivalence-function}}.
==== string-hash
-(string-hash STRING [BOUND START END])
+(string-hash STRING [BOUND START END RANDOMIZATION])
For use with {{string=?}} as a {{hash-table-equivalence-function}}.
The optional {{START}} and {{END}} arguments may be given to limit
@@ -325,43 +341,43 @@ the hash calculation to a specific sub-section of {{STRING}}.
==== string-ci-hash
-(string-hash-ci STRING [BOUND START END])
-(string-ci-hash STRING [BOUND START END])
+(string-hash-ci STRING [BOUND START END RANDOMIZATION])
+(string-ci-hash STRING [BOUND START END RANDOMIZATION])
For use with {{string-ci=?}} as a {{hash-table-equivalence-function}}.
==== eq?-hash
-(eq?-hash OBJECT [BOUND])
+(eq?-hash OBJECT [BOUND RANDOMIZATION])
For use with {{eq?}} as a {{hash-table-equivalence-function}}.
==== eqv?-hash
-(eqv?-hash OBJECT [BOUND])
+(eqv?-hash OBJECT [BOUND RANDOMIZATION])
For use with {{eqv?}} as a {{hash-table-equivalence-function}}.
==== equal?-hash
-(equal?-hash OBJECT [BOUND])
+(equal?-hash OBJECT [BOUND RANDOMIZATION])
For use with {{equal?}} as a {{hash-table-equivalence-function}}.
==== hash
-(hash OBJECT [BOUND])
+(hash OBJECT [BOUND RANDOMIZATION])
Synonym for {{equal?-hash}}.
==== hash-by-identity
-(hash-by-identity OBJECT [BOUND])
+(hash-by-identity OBJECT [BOUND RANDOMIZATION])
Synonym for {{eq?-hash}}.
diff --git a/srfi-69.scm b/srfi-69.scm
index febfe7e..f4c630e 100644
--- a/srfi-69.scm
+++ b/srfi-69.scm
@@ -105,16 +105,18 @@
(define-constant unknown-immediate-hash-value 262)
(define-constant hash-default-bound 536870912)
+(define hash-default-randomization
+ (##core#inline "C_random_fixnum" hash-default-bound))
;; Force Hash to Bounded Fixnum:
(define-inline (%fxabs fxn)
(if (fx< fxn 0) (fxneg fxn) fxn ) )
-(define-inline (%hash/limit hsh lim)
+(define-inline (%hash/limit hsh lim rnd)
;; use 32-bit mask to have identical hashes on 64-bit platforms
(fxmod (fxand (foreign-value "C_MOST_POSITIVE_32_BIT_FIXNUM" int)
- (%fxabs hsh))
+ (fxxor (%fxabs hsh) rnd))
lim) )
;; Number Hash:
@@ -147,11 +149,12 @@
(cond [(fixnum? obj) obj]
[else (%non-fixnum-number-hash obj)] ) )
-(define (number-hash obj #!optional (bound hash-default-bound))
+(define (number-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(unless (number? obj)
(##sys#signal-hook #:type 'number-hash "invalid number" obj) )
(##sys#check-exact bound 'number-hash)
- (%hash/limit (%number-hash obj) bound) )
+ (%hash/limit (%number-hash obj) bound randomization) )
;; Object UID Hash:
@@ -162,9 +165,10 @@
(define-inline (%object-uid-hash obj)
(*equal?-hash obj) )
-(define (object-uid-hash obj #!optional (bound hash-default-bound))
+(define (object-uid-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-exact bound 'object-uid-hash)
- (%hash/limit (%object-uid-hash obj) bound) )
+ (%hash/limit (%object-uid-hash obj) bound randomization) )
;; Symbol Hash:
@@ -175,10 +179,11 @@
(define-inline (%symbol-hash obj)
(%string-hash (##sys#slot obj 1)) )
-(define (symbol-hash obj #!optional (bound hash-default-bound))
+(define (symbol-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-symbol obj 'symbol-hash)
(##sys#check-exact bound 'symbol-hash)
- (%hash/limit (%symbol-hash obj) bound) )
+ (%hash/limit (%symbol-hash obj) bound randomization) )
;; Keyword Hash:
@@ -195,10 +200,11 @@
(define-inline (%keyword-hash obj)
(%string-hash (##sys#slot obj 1)) )
-(define (keyword-hash obj #!optional (bound hash-default-bound))
+(define (keyword-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-keyword obj 'keyword-hash)
(##sys#check-exact bound 'keyword-hash)
- (%hash/limit (%keyword-hash obj) bound) )
+ (%hash/limit (%keyword-hash obj) bound randomization) )
;; Eq Hash:
@@ -221,9 +227,10 @@
[(%immediate? obj) unknown-immediate-hash-value]
[else (%object-uid-hash obj) ] ) )
-(define (eq?-hash obj #!optional (bound hash-default-bound))
+(define (eq?-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-exact bound 'eq?-hash)
- (%hash/limit (*eq?-hash obj) bound) )
+ (%hash/limit (*eq?-hash obj) bound randomization) )
(define hash-by-identity eq?-hash)
@@ -247,9 +254,10 @@
[(%immediate? obj) unknown-immediate-hash-value]
[else (%object-uid-hash obj) ] ) )
-(define (eqv?-hash obj #!optional (bound hash-default-bound))
+(define (eqv?-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-exact bound 'eqv?-hash)
- (%hash/limit (*eqv?-hash obj) bound) )
+ (%hash/limit (*eqv?-hash obj) bound randomization) )
;; Equal Hash:
@@ -327,37 +335,38 @@
;
(recursive-hash obj 0) )
-(define (equal?-hash obj #!optional (bound hash-default-bound))
+(define (equal?-hash obj #!optional (bound hash-default-bound)
+ (randomization hash-default-randomization))
(##sys#check-exact bound 'hash)
- (%hash/limit (*equal?-hash obj) bound) )
+ (%hash/limit (*equal?-hash obj) bound randomization) )
(define hash equal?-hash)
;; String Hash:
-(define (string-hash str #!optional (bound hash-default-bound) . start+end)
+(define (string-hash str #!optional (bound hash-default-bound) start end
+ (randomization hash-default-randomization))
(##sys#check-string str 'string-hash)
(##sys#check-exact bound 'string-hash)
- (let ((str (if (pair? start+end)
- (let-optionals start+end ((start 0)
- (end (##sys#size str)))
- (##sys#check-range start 0 (##sys#size str) 'string-hash)
- (##sys#check-range end 0 (##sys#size str) 'string-hash)
- (##sys#substring str start end) )
- str) ) )
- (%hash/limit (%string-hash str) bound) ) )
-
-(define (string-ci-hash str #!optional (bound hash-default-bound) . start+end)
+ (let ((str (if start
+ (let ((end (or end (##sys#size str))))
+ (##sys#check-range start 0 (##sys#size str) 'string-hash)
+ (##sys#check-range end 0 (##sys#size str) 'string-hash)
+ (##sys#substring str start end))
+ str)) )
+ (%hash/limit (%string-hash str) bound randomization) ) )
+
+(define (string-ci-hash str #!optional (bound hash-default-bound) start end
+ (randomization hash-default-randomization))
(##sys#check-string str 'string-ci-hash)
(##sys#check-exact bound 'string-ci-hash)
- (let ((str (if (pair? start+end)
- (let-optionals start+end ((start 0)
- (end (##sys#size str)))
- (##sys#check-range start 0 (##sys#size str) 'string-hash-ci)
- (##sys#check-range end 0 (##sys#size str) 'string-hash-ci)
- (##sys#substring str start end) )
- str) ) )
- (%hash/limit (%string-ci-hash str) bound) ) )
+ (let ((str (if start
+ (let ((end (or end (##sys#size str))))
+ (##sys#check-range start 0 (##sys#size str) 'string-hash)
+ (##sys#check-range end 0 (##sys#size str) 'string-hash)
+ (##sys#substring str start end))
+ str)) )
+ (%hash/limit (%string-ci-hash str) bound randomization) ) )
(define string-hash-ci string-ci-hash)
@@ -405,16 +414,17 @@
(define *make-hash-table
(let ([make-vector make-vector])
(lambda (test hash len min-load max-load weak-keys weak-values initial
- #!optional (vec (make-vector len '())))
+ randomization #!optional (vec (make-vector len '())))
(##sys#make-structure 'hash-table
- vec 0 test hash min-load max-load #f #f initial) ) ) )
+ vec 0 test hash min-load max-load #f #f initial randomization) ) ) )
;; SRFI-69 & SRFI-90'ish.
;;
;; Argument list is the pattern
;;
;; (make-hash-table #!optional test hash size
-;; #!key test hash size initial min-load max-load weak-keys weak-values)
+;; #!key test hash size initial randomization
+;; min-load max-load weak-keys weak-values)
;;
;; where a keyword argument takes precedence over the corresponding optional
;; argument. Keyword arguments MUST come after optional & required
@@ -435,6 +445,7 @@
[hash #f]
[size hash-table-default-length]
[initial #f]
+ [randomization (##core#inline "C_random_fixnum" hash-default-bound)]
[min-load hash-table-default-min-load]
[max-load hash-table-default-max-load]
[weak-keys #f]
@@ -501,6 +512,9 @@
(set! size (fxmin hash-table-max-length val))]
[(#:initial)
(set! initial (lambda () val))]
+ [(#:randomization)
+ (##sys#check-exact val 'make-hash-table)
+ (set! randomization val)]
[(#:min-load)
(##sys#check-inexact val 'make-hash-table)
(unless (and (fp< 0.0 val) (fp< val 1.0))
@@ -533,7 +547,8 @@
(warning 'make-hash-table "user test without user hash")
(set! hash equal?-hash) ) ) ) )
; Done
- (*make-hash-table test hash size min-load max-load weak-keys weak-values initial) ) ) ) ) )
+ (*make-hash-table test hash size min-load max-load
+ weak-keys weak-values initial randomization) ) ) ) ) )
;; Hash-Table Predicate:
@@ -580,9 +595,13 @@
(and-let* ([thunk (##sys#slot ht 9)])
(thunk) ) )
+(define (hash-table-randomization ht)
+ (##sys#check-structure ht 'hash-table 'hash-table-initial)
+ (##sys#slot ht 10) )
+
;; hash-table-rehash!:
-(define (hash-table-rehash! vec1 vec2 hash)
+(define (hash-table-rehash! vec1 vec2 hash rnd)
(let ([len1 (##sys#size vec1)]
[len2 (##sys#size vec2)] )
(do ([i 0 (fx+ i 1)])
@@ -591,7 +610,7 @@
(unless (null? bucket)
(let* ([pare (##sys#slot bucket 0)]
[key (##sys#slot pare 0)]
- [hshidx (hash key len2)] )
+ [hshidx (hash key len2 rnd)] )
(##sys#setslot vec2 hshidx
(cons (cons key (##sys#slot pare 1)) (##sys#slot vec2 hshidx)))
(loop (##sys#slot bucket 1)) ) ) ) ) ) )
@@ -602,7 +621,7 @@
(let* ([deslen (fxmin hash-table-max-length (fx* len hash-table-new-length-factor))]
[newlen (hash-table-canonical-length hash-table-prime-lengths deslen)]
[vec2 (make-vector newlen '())] )
- (hash-table-rehash! vec vec2 (##sys#slot ht 4))
+ (hash-table-rehash! vec vec2 (##sys#slot ht 4) (##sys#slot ht 10))
(##sys#setslot ht 1 vec2) ) )
;; hash-table-check-resize!:
@@ -633,7 +652,7 @@
(##sys#slot ht 2)
(##sys#slot ht 5) (##sys#slot ht 6)
(##sys#slot ht 7) (##sys#slot ht 8)
- (##sys#slot ht 9)
+ (##sys#slot ht 9) (##sys#slot ht 10)
vec2)]
(##sys#setslot vec2 i
(let copy-loop ([bucket (##sys#slot vec1 i)])
@@ -671,9 +690,10 @@
(hash-table-check-resize! ht newsiz)
(let ([hash (##sys#slot ht 4)]
[test (##sys#slot ht 3)]
- [vec (##sys#slot ht 1)] )
+ [vec (##sys#slot ht 1)]
+ [rnd (##sys#slot ht 10)])
(let* ([len (##sys#size vec)]
- [hshidx (hash key len)]
+ [hshidx (hash key len rnd)]
[bucket0 (##sys#slot vec hshidx)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
@@ -710,9 +730,10 @@
(hash-table-check-resize! ht newsiz)
(let ([hash (##sys#slot ht 4)]
[test (##sys#slot ht 3)]
- [vec (##sys#slot ht 1)] )
+ [vec (##sys#slot ht 1)]
+ [rnd (##sys#slot ht 10)])
(let* ([len (##sys#size vec)]
- [hshidx (hash key len)]
+ [hshidx (hash key len rnd)]
[bucket0 (##sys#slot vec hshidx)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
@@ -755,9 +776,10 @@
(hash-table-check-resize! ht newsiz)
(let ([hash (##sys#slot ht 4)]
[test (##sys#slot ht 3)]
- [vec (##sys#slot ht 1)] )
+ [vec (##sys#slot ht 1)]
+ [rnd (##sys#slot ht 10)])
(let* ([len (##sys#size vec)]
- [hshidx (hash key len)]
+ [hshidx (hash key len rnd)]
[bucket0 (##sys#slot vec hshidx)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
@@ -794,9 +816,10 @@
(##sys#check-structure ht 'hash-table 'hash-table-ref)
(##sys#check-closure def 'hash-table-ref)
(let ([vec (##sys#slot ht 1)]
- [test (##sys#slot ht 3)] )
+ [test (##sys#slot ht 3)]
+ [rnd (##sys#slot ht 10)])
(let* ([hash (##sys#slot ht 4)]
- [hshidx (hash key (##sys#size vec))] )
+ [hshidx (hash key (##sys#size vec) rnd)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
(let loop ([bucket (##sys#slot vec hshidx)])
@@ -822,9 +845,10 @@
(lambda (ht key def)
(##sys#check-structure ht 'hash-table 'hash-table-ref/default)
(let ([vec (##sys#slot ht 1)]
- [test (##sys#slot ht 3)] )
+ [test (##sys#slot ht 3)]
+ [rnd (##sys#slot ht 10)])
(let* ([hash (##sys#slot ht 4)]
- [hshidx (hash key (##sys#size vec))] )
+ [hshidx (hash key (##sys#size vec) rnd)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
(let loop ([bucket (##sys#slot vec hshidx)])
@@ -848,9 +872,10 @@
(lambda (ht key)
(##sys#check-structure ht 'hash-table 'hash-table-exists?)
(let ([vec (##sys#slot ht 1)]
- [test (##sys#slot ht 3)] )
+ [test (##sys#slot ht 3)]
+ [rnd (##sys#slot ht 10)])
(let* ([hash (##sys#slot ht 4)]
- [hshidx (hash key (##sys#size vec))] )
+ [hshidx (hash key (##sys#size vec) rnd)] )
(if (eq? core-eq? test)
; Fast path (eq? is rewritten by the compiler):
(let loop ([bucket (##sys#slot vec hshidx)])
@@ -874,7 +899,8 @@
(let* ([vec (##sys#slot ht 1)]
[len (##sys#size vec)]
[hash (##sys#slot ht 4)]
- [hshidx (hash key len)] )
+ [rnd (##sys#slot ht 10)]
+ [hshidx (hash key len rnd)] )
(let ([test (##sys#slot ht 3)]
[newsiz (fx- (##sys#slot ht 2) 1)]
[bucket0 (##sys#slot vec hshidx)] )
diff --git a/tests/hash-table-tests.scm b/tests/hash-table-tests.scm
index 524c40d..6737c8f 100644
--- a/tests/hash-table-tests.scm
+++ b/tests/hash-table-tests.scm
@@ -38,7 +38,7 @@
(print "HT - All Parameters")
(set! ht (make-hash-table eqv? eqv?-hash 23
#:test equal? #:hash equal?-hash
- #:initial 'foo
+ #:initial 'foo #:randomization 30
#:size 500
#:min-load 0.45 #:max-load 0.85
#:weak-keys #t #:weak-values #t))
diff --git a/types.db b/types.db
index 9f97c46..3ee83db 100644
--- a/types.db
+++ b/types.db
@@ -2448,11 +2448,11 @@
;; srfi-69
(alist->hash-table (#(procedure #:clean #:enforce) alist->hash-table ((list-of pair) #!rest) (struct hash-table)))
-(eq?-hash (#(procedure #:clean #:enforce) eq?-hash (* #!optional fixnum) fixnum))
-(equal?-hash (#(procedure #:clean #:enforce) equal?-hash (* #!optional fixnum) fixnum))
-(eqv?-hash (#(procedure #:clean #:enforce) eqv?-hash (* #!optional fixnum) fixnum))
-(hash (#(procedure #:pure #:enforce) hash (* #!optional fixnum) fixnum))
-(hash-by-identity (#(procedure #:pure #:enforce) hash-by-identity (* #!optional fixnum) fixnum))
+(eq?-hash (#(procedure #:clean #:enforce) eq?-hash (* #!optional fixnum fixnum) fixnum))
+(equal?-hash (#(procedure #:clean #:enforce) equal?-hash (* #!optional fixnum fixnum) fixnum))
+(eqv?-hash (#(procedure #:clean #:enforce) eqv?-hash (* #!optional fixnum fixnum) fixnum))
+(hash (#(procedure #:pure #:enforce) hash (* #!optional fixnum fixnum) fixnum))
+(hash-by-identity (#(procedure #:pure #:enforce) hash-by-identity (* #!optional fixnum fixnum) fixnum))
(hash-table->alist (#(procedure #:clean #:enforce) hash-table->alist ((struct hash-table)) (list-of pair)))
(hash-table-clear! (#(procedure #:clean #:enforce) hash-table-clear! ((struct hash-table)) undefined))
(hash-table-copy (#(procedure #:clean #:enforce) hash-table-copy ((struct hash-table)) (struct hash-table)))
@@ -2468,6 +2468,8 @@
(hash-table-hash-function (#(procedure #:clean #:enforce) hash-table-hash-function ((struct hash-table)) (procedure (* fixnum) fixnum))
(((struct hash-table)) (##sys#slot #(1) '4)))
+(hash-table-randomization (#(procedure #:clean #:enforce) hash-table-randomization ((struct hash-table)) fixnum)
+ (((struct hash-table)) (##sys#slot #(1) '10)))
(hash-table-initial (#(procedure #:clean #:enforce) hash-table-initial ((struct hash-table)) *))
(hash-table-keys (#(procedure #:clean #:enforce) hash-table-keys ((struct hash-table)) list))
(hash-table-map (#(procedure #:clean #:enforce) hash-table-map ((struct hash-table) (procedure (* *) *)) list))
@@ -2504,15 +2506,15 @@
;;XXX if we want to hardcode hash-default-bound here, we could rewrite the 1-arg case...
; (applies to all hash-functions)
-(keyword-hash (#(procedure #:clean #:enforce) keyword-hash (* #!optional fixnum) fixnum))
+(keyword-hash (#(procedure #:clean #:enforce) keyword-hash (* #!optional fixnum fixnum) fixnum))
(make-hash-table (#(procedure #:clean #:enforce) make-hash-table (#!rest) (struct hash-table)))
-(number-hash (#(procedure #:clean #:enforce) number-hash (fixnum #!optional fixnum) fixnum))
-(object-uid-hash (#(procedure #:clean #:enforce) object-uid-hash (* #!optional fixnum) fixnum))
-(symbol-hash (#(procedure #:clean #:enforce) symbol-hash (symbol #!optional fixnum) fixnum))
-(string-hash (#(procedure #:clean #:enforce) string-hash (string #!optional fixnum fixnum fixnum) number))
-(string-hash-ci (#(procedure #:clean #:enforce) string-hash-ci (string #!optional fixnum fixnum fixnum) number))
-(string-ci-hash (#(procedure #:clean #:enforce) string-ci-hash (string #!optional fixnum fixnum fixnum) number))
+(number-hash (#(procedure #:clean #:enforce) number-hash (fixnum #!optional fixnum fixnum) fixnum))
+(object-uid-hash (#(procedure #:clean #:enforce) object-uid-hash (* #!optional fixnum fixnum) fixnum))
+(symbol-hash (#(procedure #:clean #:enforce) symbol-hash (symbol #!optional fixnum fixnum) fixnum))
+(string-hash (#(procedure #:clean #:enforce) string-hash (string #!optional fixnum fixnum fixnum fixnum) number))
+(string-hash-ci (#(procedure #:clean #:enforce) string-hash-ci (string #!optional fixnum fixnum fixnum fixnum) number))
+(string-ci-hash (#(procedure #:clean #:enforce) string-ci-hash (string #!optional fixnum fixnum fixnum fixnum) number))
;; tcp