isc_lib_register();
isc_log_setcontext(dctx->lctx);
dns_log_setcontext(dctx->lctx);
+ isc_hash_set_initializer(dctx->hashinit);
}
- isc_hash_set_initializer(dctx->hashinit);
-
s = isc_mem_strdup(mctx, parameters);
if (s == NULL) {
result = ISC_R_NOMEMORY;
length = 16;
return (isc_hash_function_reverse(name->ndata, length,
- case_sensitive, NULL));
+ case_sensitive));
}
unsigned int
return (0);
return (isc_hash_function_reverse(name->ndata, name->length,
- case_sensitive, NULL));
+ case_sensitive));
}
dns_namereln_t
{
hash = isc_hash_function(&gluenode->node,
sizeof(gluenode->node),
- true, NULL) %
+ true) %
version->glue_table_size;
nextgluenode = gluenode->next;
gluenode->next = version->glue_table[hash];
* the node pointer is a fixed value that won't change for a DB
* version and can be compared directly.
*/
- idx = isc_hash_function(&node, sizeof(node), true, NULL) %
+ idx = isc_hash_function(&node, sizeof(node), true) %
rbtversion->glue_table_size;
restart:
RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write);
if (ISC_UNLIKELY(rehash_gluetable(rbtversion))) {
- idx = isc_hash_function(&node, sizeof(node),
- true, NULL) %
+ idx = isc_hash_function(&node, sizeof(node), true) %
rbtversion->glue_table_size;
}
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
+#if defined(WIN32) || defined(WIN64)
+#include <malloc.h>
+#endif
#include "isc/hash.h" // IWYU pragma: keep
#include "isc/likely.h"
#include "isc/result.h"
#include "isc/types.h"
#include "isc/util.h"
+#include "isc/siphash.h"
+#include "isc/string.h"
-static uint32_t fnv_offset_basis;
-static isc_once_t fnv_once = ISC_ONCE_INIT;
-static bool fnv_initialized = false;
+#include "entropy_private.h"
-static unsigned char maptolower[] = {
+static uint8_t isc_hash_key[16];
+static bool hash_initialized = false;
+static isc_once_t isc_hash_once = ISC_ONCE_INIT;
+
+static void
+isc_hash_initialize(void) {
+ uint64_t key[2] = { 0, 1 };
+#if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /*
+ * Set a constant key to help in problem reproduction should
+ * fuzzing find a crash or a hang.
+ */
+#else
+ isc_entropy_get(key, sizeof(key));
+#endif
+ memmove(isc_hash_key, key, sizeof(isc_hash_key));
+ hash_initialized = true;
+}
+
+static uint8_t maptolower[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
-static void
-fnv_initialize(void) {
- /*
- * This function should not leave fnv_offset_basis set to
- * 0. Also, after this function has been called, if it is called
- * again, it should not change fnv_offset_basis.
- */
- while (fnv_offset_basis == 0) {
- fnv_offset_basis = isc_random32();
- }
-
- fnv_initialized = true;
-}
-
const void *
isc_hash_get_initializer(void) {
- if (ISC_UNLIKELY(!fnv_initialized))
- RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
- ISC_R_SUCCESS);
+ if (ISC_UNLIKELY(!hash_initialized)) {
+ RUNTIME_CHECK(isc_once_do(&isc_hash_once,
+ isc_hash_initialize)
+ == ISC_R_SUCCESS);
+ }
- return (&fnv_offset_basis);
+ return (isc_hash_key);
}
void
REQUIRE(initializer != NULL);
/*
- * Ensure that fnv_initialize() is not called after
+ * Ensure that isc_hash_initialize() is not called after
* isc_hash_set_initializer() is called.
*/
- if (ISC_UNLIKELY(!fnv_initialized))
- RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
- ISC_R_SUCCESS);
+ if (ISC_UNLIKELY(!hash_initialized)) {
+ RUNTIME_CHECK(isc_once_do(&isc_hash_once,
+ isc_hash_initialize)
+ == ISC_R_SUCCESS);
+ }
- fnv_offset_basis = *((const unsigned int *)initializer);
+ memmove(isc_hash_key, initializer, sizeof(isc_hash_key));
}
-#define FNV_32_PRIME ((uint32_t)0x01000193)
-
-uint32_t
-isc_hash_function(const void *data, size_t length, bool case_sensitive,
- const uint32_t *previous_hashp)
+uint64_t
+isc_hash_function(const void *data, const size_t length,
+ const bool case_sensitive)
{
- uint32_t hval;
- const unsigned char *bp;
- const unsigned char *be;
+ uint64_t hval;
REQUIRE(length == 0 || data != NULL);
- if (ISC_UNLIKELY(!fnv_initialized)) {
- RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
- ISC_R_SUCCESS);
- }
-
- hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp
- : fnv_offset_basis;
-
- if (length == 0) {
- return (hval);
- }
-
- bp = (const unsigned char *)data;
- be = bp + length;
-
- /*
- * Fowler-Noll-Vo FNV-1a hash function.
- *
- * NOTE: A random FNV offset basis is used by default to avoid
- * collision attacks as the hash function is reversible. This
- * makes the mapping non-deterministic, but the distribution in
- * the domain is still uniform.
- */
+ RUNTIME_CHECK(isc_once_do(&isc_hash_once,
+ isc_hash_initialize) == ISC_R_SUCCESS);
if (case_sensitive) {
- while (bp < be) {
- hval ^= *bp++;
- hval *= FNV_32_PRIME;
- }
+ isc_siphash24(isc_hash_key, data, length, (uint8_t *)&hval);
} else {
- while (bp < be) {
- hval ^= maptolower[*bp++];
- hval *= FNV_32_PRIME;
+ uint8_t input[1024];
+ REQUIRE(length <= 1024);
+ for (unsigned int i = 0; i < length; i++) {
+ input[i] = maptolower[((const uint8_t *)data)[i]];
}
+ isc_siphash24(isc_hash_key, input, length, (uint8_t *)&hval);
}
return (hval);
}
-uint32_t
-isc_hash_function_reverse(const void *data, size_t length, bool case_sensitive,
- const uint32_t *previous_hashp)
+uint64_t
+isc_hash_function_reverse(const void *data, const size_t length,
+ const bool case_sensitive)
{
- uint32_t hval;
- const unsigned char *bp;
- const unsigned char *be;
+ uint64_t hval;
+#if defined(WIN32) || defined(WIN64)
+ uint8_t *input = _alloca(length);
+ INSIST(buf != NULL);
+#else
+ uint8_t input[length];
+#endif
REQUIRE(length == 0 || data != NULL);
- if (ISC_UNLIKELY(!fnv_initialized)) {
- RUNTIME_CHECK(isc_once_do(&fnv_once, fnv_initialize) ==
- ISC_R_SUCCESS);
- }
-
- hval = ISC_UNLIKELY(previous_hashp != NULL) ? *previous_hashp
- : fnv_offset_basis;
-
- if (length == 0) {
- return (hval);
- }
-
- bp = (const unsigned char *)data;
- be = bp + length;
-
- /*
- * Fowler-Noll-Vo FNV-1a hash function.
- *
- * NOTE: A random FNV offset basis is used by default to avoid
- * collision attacks as the hash function is reversible. This
- * makes the mapping non-deterministic, but the distribution in
- * the domain is still uniform.
- */
+ RUNTIME_CHECK(isc_once_do(&isc_hash_once,
+ isc_hash_initialize) == ISC_R_SUCCESS);
if (case_sensitive) {
- while (--be >= bp) {
- hval ^= *be;
- hval *= FNV_32_PRIME;
+ for (unsigned int i = 0, j = length - 1; i < length; i++, j--) {
+ input[i] = ((const uint8_t *)data)[j];
}
} else {
- while (--be >= bp) {
- hval ^= maptolower[*be];
- hval *= FNV_32_PRIME;
+ for (unsigned int i = 0, j = length - 1; i < length; i++, j--) {
+ input[i] = maptolower[((const uint8_t *)data)[j]];
}
}
+ isc_siphash24(isc_hash_key, input, length, (uint8_t *)&hval);
return (hval);
}
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
- hash = isc_hash_function(key, keysize, true, NULL);
+ hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
REQUIRE(key != NULL && keysize > 0);
REQUIRE(valuep == NULL || *valuep == NULL);
- hash = isc_hash_function(key, keysize, true, NULL);
+ hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
REQUIRE(key != NULL && keysize > 0);
prev = NULL;
- hash = isc_hash_function(key, keysize, true, NULL);
+ hash = isc_hash_function(key, keysize, true);
node = ht->table[hash & ht->mask];
while (node != NULL) {
if (keysize == node->keysize &&
it->cur = ht->table[it->i];
}
- hash = isc_hash_function(to_delete->key, to_delete->keysize, true,
- NULL);
+ hash = isc_hash_function(to_delete->key, to_delete->keysize, true);
node = ht->table[hash & ht->mask];
while (node != to_delete) {
prev = node;
void
isc_hash_set_initializer(const void *initializer);
-uint32_t
-isc_hash_function(const void *data, size_t length,
- bool case_sensitive,
- const uint32_t *previous_hashp);
-uint32_t
-isc_hash_function_reverse(const void *data, size_t length,
- bool case_sensitive,
- const uint32_t *previous_hashp);
+uint64_t
+isc_hash_function(const void *data, const size_t length, const bool case_sensitive);
+uint64_t
+isc_hash_function_reverse(const void *data, const size_t length, const bool case_sensitive);
/*!<
* \brief Calculate a hash over data.
*
if (mctx->debuglist == NULL)
return;
- hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
+ hash = isc_hash_function(&ptr, sizeof(ptr), true);
idx = hash % DEBUG_TABLE_COUNT;
dl = malloc(sizeof(debuglink_t));
if (mctx->debuglist == NULL)
return;
- hash = isc_hash_function(&ptr, sizeof(ptr), true, NULL);
+ hash = isc_hash_function(&ptr, sizeof(ptr), true);
idx = hash % DEBUG_TABLE_COUNT;
dl = ISC_LIST_HEAD(mctx->debuglist[idx]);
#include <stdbool.h>
#include <stdio.h>
+#if defined(WIN32) || defined(WIN64)
+#include <malloc.h>
+#endif
#include <isc/buffer.h>
#include <isc/hash.h>
p = 0;
}
- h = isc_hash_function(s, length, true, NULL);
- if (!address_only)
- h = isc_hash_function(&p, sizeof(p), true, &h);
+ uint8_t buf[sizeof(struct sockaddr_storage) + sizeof(p)];
+ memmove(buf, s, length);
+ if (!address_only) {
+ memmove(buf + length, &p, sizeof(p));
+ h = isc_hash_function(buf, length + sizeof(p), true);
+ } else {
+ h = isc_hash_function(buf, length, true);
+ }
return (h);
}
#define TEST_INPUT(x) (x), sizeof(x)-1
-typedef struct hash_testcase {
- const char *input;
- size_t input_len;
- const char *result;
- int repeats;
-} hash_testcase_t;
-
/*Hash function test */
static void
isc_hash_function_test(void **state) {
UNUSED(state);
- /* Incremental hashing */
-
- h1 = isc_hash_function(NULL, 0, true, NULL);
- h1 = isc_hash_function("This ", 5, true, &h1);
- h1 = isc_hash_function("is ", 3, true, &h1);
- h1 = isc_hash_function("a long test", 12, true, &h1);
-
- h2 = isc_hash_function("This is a long test", 20,
- true, NULL);
-
- assert_int_equal(h1, h2);
-
/* Immutability of hash function */
- h1 = isc_hash_function(NULL, 0, true, NULL);
- h2 = isc_hash_function(NULL, 0, true, NULL);
+ h1 = isc_hash_function(NULL, 0, true);
+ h2 = isc_hash_function(NULL, 0, true);
assert_int_equal(h1, h2);
/* Hash function characteristics */
- h1 = isc_hash_function("Hello world", 12, true, NULL);
- h2 = isc_hash_function("Hello world", 12, true, NULL);
+ h1 = isc_hash_function("Hello world", 12, true);
+ h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
/* Case */
- h1 = isc_hash_function("Hello world", 12, false, NULL);
- h2 = isc_hash_function("heLLo WorLd", 12, false, NULL);
+ h1 = isc_hash_function("Hello world", 12, false);
+ h2 = isc_hash_function("heLLo WorLd", 12, false);
assert_int_equal(h1, h2);
/* Unequal */
- h1 = isc_hash_function("Hello world", 12, true, NULL);
- h2 = isc_hash_function("heLLo WorLd", 12, true, NULL);
+ h1 = isc_hash_function("Hello world", 12, true);
+ h2 = isc_hash_function("heLLo WorLd", 12, true);
assert_int_not_equal(h1, h2);
}
UNUSED(state);
- /* Incremental hashing */
-
- h1 = isc_hash_function_reverse(NULL, 0, true, NULL);
- h1 = isc_hash_function_reverse("\000", 1, true, &h1);
- h1 = isc_hash_function_reverse("\003org", 4, true, &h1);
- h1 = isc_hash_function_reverse("\007example", 8, true, &h1);
-
- h2 = isc_hash_function_reverse("\007example\003org\000", 13,
- true, NULL);
-
- assert_int_equal(h1, h2);
-
/* Immutability of hash function */
- h1 = isc_hash_function_reverse(NULL, 0, true, NULL);
- h2 = isc_hash_function_reverse(NULL, 0, true, NULL);
+ h1 = isc_hash_function_reverse(NULL, 0, true);
+ h2 = isc_hash_function_reverse(NULL, 0, true);
assert_int_equal(h1, h2);
/* Hash function characteristics */
- h1 = isc_hash_function_reverse("Hello world", 12, true, NULL);
- h2 = isc_hash_function_reverse("Hello world", 12, true, NULL);
+ h1 = isc_hash_function_reverse("Hello world", 12, true);
+ h2 = isc_hash_function_reverse("Hello world", 12, true);
assert_int_equal(h1, h2);
/* Case */
- h1 = isc_hash_function_reverse("Hello world", 12, false, NULL);
- h2 = isc_hash_function_reverse("heLLo WorLd", 12, false, NULL);
+ h1 = isc_hash_function_reverse("Hello world", 12, false);
+ h2 = isc_hash_function_reverse("heLLo WorLd", 12, false);
assert_int_equal(h1, h2);
/* Unequal */
- h1 = isc_hash_function_reverse("Hello world", 12, true, NULL);
- h2 = isc_hash_function_reverse("heLLo WorLd", 12, true, NULL);
+ h1 = isc_hash_function_reverse("Hello world", 12, true);
+ h2 = isc_hash_function_reverse("heLLo WorLd", 12, true);
assert_true(h1 != h2);
}
UNUSED(state);
- h1 = isc_hash_function("Hello world", 12, true, NULL);
- h2 = isc_hash_function("Hello world", 12, true, NULL);
+ h1 = isc_hash_function("Hello world", 12, true);
+ h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
isc_hash_set_initializer(isc_hash_get_initializer());
/* Hash value must not change */
- h2 = isc_hash_function("Hello world", 12, true, NULL);
+ h2 = isc_hash_function("Hello world", 12, true);
assert_int_equal(h1, h2);
}
isc_fsaccess_remove
isc_fsaccess_set
isc_hash_function
-isc_hash_function_reverse
isc_hash_get_initializer
isc_hash_set_initializer
isc_heap_create