mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-12 20:49:59 -04:00
Convert isc_hash functions to use isc_siphash24
(cherry picked from commit 2e7d82443f)
This commit is contained in:
parent
2188a58171
commit
4e04e3d861
10 changed files with 114 additions and 177 deletions
|
|
@ -80,10 +80,9 @@ dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) {
|
|||
length = 16;
|
||||
|
||||
return (isc_hash_function_reverse(name->ndata, length,
|
||||
case_sensitive, NULL));
|
||||
case_sensitive));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
|
|
@ -480,7 +480,7 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
|
|||
return (0);
|
||||
|
||||
return (isc_hash_function_reverse(name->ndata, name->length,
|
||||
case_sensitive, NULL));
|
||||
case_sensitive));
|
||||
}
|
||||
|
||||
dns_namereln_t
|
||||
|
|
|
|||
|
|
@ -9655,7 +9655,7 @@ rehash_gluetable(rbtdb_version_t *version) {
|
|||
{
|
||||
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];
|
||||
|
|
@ -9823,7 +9823,7 @@ rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
|
|||
* 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:
|
||||
|
|
@ -9999,8 +9999,7 @@ no_glue:
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
168
lib/isc/hash.c
168
lib/isc/hash.c
|
|
@ -18,6 +18,9 @@
|
|||
#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"
|
||||
|
|
@ -26,12 +29,31 @@
|
|||
#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,
|
||||
|
|
@ -66,27 +88,15 @@ static unsigned char maptolower[] = {
|
|||
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
|
||||
|
|
@ -94,112 +104,70 @@ isc_hash_set_initializer(const void *initializer) {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ isc_ht_add(isc_ht_t *ht, const unsigned char *key,
|
|||
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 &&
|
||||
|
|
@ -165,7 +165,7 @@ isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
|
|||
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 &&
|
||||
|
|
@ -190,7 +190,7 @@ isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t 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 &&
|
||||
|
|
@ -305,8 +305,7 @@ isc_ht_iter_delcurrent_next(isc_ht_iter_t *it) {
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -29,14 +29,10 @@ isc_hash_get_initializer(void);
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) {
|
|||
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));
|
||||
|
|
@ -298,7 +298,7 @@ delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size,
|
|||
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]);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/hash.h>
|
||||
|
|
@ -224,9 +227,14 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only) {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,13 +39,6 @@
|
|||
|
||||
#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) {
|
||||
|
|
@ -54,39 +47,27 @@ 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);
|
||||
}
|
||||
|
|
@ -99,39 +80,27 @@ isc_hash_function_reverse_test(void **state) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
@ -144,15 +113,15 @@ isc_hash_initializer_test(void **state) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,6 @@ isc_fsaccess_changeowner
|
|||
isc_fsaccess_remove
|
||||
isc_fsaccess_set
|
||||
isc_hash_function
|
||||
isc_hash_function_reverse
|
||||
isc_hash_get_initializer
|
||||
isc_hash_set_initializer
|
||||
isc_heap_create
|
||||
|
|
|
|||
Loading…
Reference in a new issue