| @@ -26,6 +26,7 @@ |
| #include <stddef.h> /* for offsetof() */ |
| |
| #include "hash.h" |
| + | #include "rand.h" |
| |
| /* random patterns for API verification */ |
| #ifdef DEBUGBUILD |
| @@ -52,14 +53,46 @@ struct hash_functions { |
| comp_function compare; |
| }; |
| |
| + | /* set at global init, read-only afterwards */ |
| + | static size_t hash_seed; |
| + | |
| + | CURLcode Curl_hash_global_init(void) |
| + | { |
| + | static bool seeded; |
| + | unsigned char buf[sizeof(size_t)]; |
| + | size_t seed = 0; |
| + | size_t i; |
| + | CURLcode result; |
| + | |
| + | if(seeded) |
| + | return CURLE_OK; |
| + | |
| + | result = Curl_rand_bytes(NULL, |
| + | #ifdef DEBUGBUILD |
| + | FALSE, |
| + | #endif |
| + | buf, sizeof(buf)); |
| + | if(result) |
| + | return result; |
| + | |
| + | for(i = 0; i < sizeof(buf); i++) |
| + | seed = (seed << 8) | buf[i]; |
| + | |
| + | hash_seed = seed ? seed : 1; |
| + | seeded = TRUE; |
| + | return CURLE_OK; |
| + | } |
| + | |
| /* @unittest 1603 |
| */ |
| - | UNITTEST size_t hash_str(const void *key, size_t key_length, size_t slots_num); |
| - | UNITTEST size_t hash_str(const void *key, size_t key_length, size_t slots_num) |
| + | UNITTEST size_t hash_str_seeded(const void *key, size_t key_length, |
| + | size_t slots_num, size_t seed); |
| + | UNITTEST size_t hash_str_seeded(const void *key, size_t key_length, |
| + | size_t slots_num, size_t seed) |
| { |
| const char *key_str = (const char *)key; |
| const char *end = key_str + key_length; |
| - | size_t h = 5381; |
| + | size_t h = 5381 ^ seed; |
| |
| while(key_str < end) { |
| size_t j = (size_t)*key_str++; |
| @@ -70,6 +103,14 @@ UNITTEST size_t hash_str(const void *key, size_t key_length, size_t slots_num) |
| return (h % slots_num); |
| } |
| |
| + | /* @unittest 1603 |
| + | */ |
| + | UNITTEST size_t hash_str(const void *key, size_t key_length, size_t slots_num); |
| + | UNITTEST size_t hash_str(const void *key, size_t key_length, size_t slots_num) |
| + | { |
| + | return hash_str_seeded(key, key_length, slots_num, hash_seed); |
| + | } |
| + | |
| /* Avoid treating the variable-length key[1] as a one-byte object. */ |
| static char *hash_elem_key(struct Curl_hash_element *he) |
| { |