On Fri, 2012-01-13 at 19:57 +1100, Bojan Smojver wrote:
> This probably wouldn't work as expected. If you had /dev/random
> selected for DEV_RANDOM, the if would fail and srand()/rand() bit
> would never get called. No?
Like attached maybe?
--
Bojan
Index: tables/apr_hash.c
===================================================================
--- tables/apr_hash.c (revision 1230868)
+++ tables/apr_hash.c (working copy)
@@ -18,6 +18,10 @@
#include "apr_general.h"
#include "apr_pools.h"
+#include "apr_time.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for rand, srand */
+#endif
#include "apr_hash.h"
@@ -75,7 +79,7 @@
apr_pool_t *pool;
apr_hash_entry_t **array;
apr_hash_index_t iterator; /* For apr_hash_first(NULL, ...) */
- unsigned int count, max;
+ unsigned int count, max, seed;
apr_hashfunc_t hash_func;
apr_hash_entry_t *free; /* List of recycled entries */
};
@@ -95,13 +99,27 @@
APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool)
{
apr_hash_t *ht;
+ apr_time_t now;
+
ht = apr_palloc(pool, sizeof(apr_hash_t));
ht->pool = pool;
ht->free = NULL;
ht->count = 0;
ht->max = INITIAL_MAX;
+#if APR_HAS_RANDOM && defined(DEV_RANDOM)
+ if (!strcmp(DEV_RANDOM, "/dev/random") ||
+ apr_generate_random_bytes(
+ (unsigned char *)&ht->seed, sizeof(ht->seed)) != APR_SUCCESS) {
+#endif
+ now = apr_time_now();
+ srand((unsigned int)((now >> 32) ^ now ^ (apr_uintptr_t)ht));
+ ht->seed = (unsigned int)(rand());
+#if APR_HAS_RANDOM && defined(DEV_RANDOM)
+ }
+#endif
ht->array = alloc_array(ht, ht->max);
- ht->hash_func = apr_hashfunc_default;
+ ht->hash_func = NULL;
+
return ht;
}
@@ -201,10 +219,10 @@
ht->max = new_max;
}
-APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key,
- apr_ssize_t *klen)
+static unsigned int apr_hashfunc_default_internal(const char *char_key,
+ apr_ssize_t *klen,
+ unsigned int hash)
{
- unsigned int hash = 0;
const unsigned char *key = (const unsigned char *)char_key;
const unsigned char *p;
apr_ssize_t i;
@@ -246,7 +264,7 @@
*
* -- Ralf S. Engelschall <[email protected]>
*/
-
+
if (*klen == APR_HASH_KEY_STRING) {
for (p = key; *p; p++) {
hash = hash * 33 + *p;
@@ -262,6 +280,11 @@
return hash;
}
+APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key,
+ apr_ssize_t *klen)
+{
+ return apr_hashfunc_default_internal(char_key, klen, 0);
+}
/*
* This is where we keep the details of the hash function and control
@@ -280,7 +303,10 @@
apr_hash_entry_t **hep, *he;
unsigned int hash;
- hash = ht->hash_func(key, &klen);
+ if (ht->hash_func)
+ hash = ht->hash_func(key, &klen);
+ else
+ hash = apr_hashfunc_default_internal(key, &klen, ht->seed);
/* scan linked list */
for (hep = &ht->array[hash & ht->max], he = *hep;
@@ -322,6 +348,7 @@
ht->free = NULL;
ht->count = orig->count;
ht->max = orig->max;
+ ht->seed = orig->seed;
ht->hash_func = orig->hash_func;
ht->array = (apr_hash_entry_t **)((char *)ht + sizeof(apr_hash_t));