Allow zero length keys in isc_hashmap

In case, we are trying to hash the empty key into the hashmap, the key
is going to have zero length.  This might happen in the unit test.
Allow this and add a unit test to ensure the empty zero-length key
doesn't hash to slot 0 as SipHash 2-4 (our hash function of choice) has
no problem with zero-length inputs.
This commit is contained in:
Ondřej Surý 2022-12-08 10:46:09 +01:00
parent 8a35d52807
commit 7cefcb6184
No known key found for this signature in database
GPG key ID: 2820F37E873DEA41
2 changed files with 29 additions and 5 deletions

View file

@ -134,7 +134,7 @@ try_nexttable(const isc_hashmap_t *hashmap, uint8_t idx) {
static void
hashmap_node_init(hashmap_node_t *node, const uint32_t hashval,
const uint8_t *key, const uint32_t keysize, void *value) {
REQUIRE(key != NULL && keysize > 0 && keysize <= UINT16_MAX);
REQUIRE(key != NULL && keysize <= UINT16_MAX);
*node = (hashmap_node_t){
.value = value,
@ -318,7 +318,6 @@ uint32_t
isc_hashmap_hash(const isc_hashmap_t *hashmap, const void *key,
uint32_t keysize) {
REQUIRE(ISC_HASHMAP_VALID(hashmap));
REQUIRE(key != NULL && keysize > 0 && keysize <= UINT16_MAX);
uint32_t hashval;
@ -332,7 +331,7 @@ isc_result_t
isc_hashmap_find(const isc_hashmap_t *hashmap, const uint32_t *hashvalp,
const void *key, uint32_t keysize, void **valuep) {
REQUIRE(ISC_HASHMAP_VALID(hashmap));
REQUIRE(key != NULL && keysize > 0 && keysize <= UINT16_MAX);
REQUIRE(key != NULL && keysize <= UINT16_MAX);
hashmap_node_t *node;
uint8_t idx = hashmap->hindex;
@ -487,7 +486,7 @@ isc_result_t
isc_hashmap_delete(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
const void *key, uint32_t keysize) {
REQUIRE(ISC_HASHMAP_VALID(hashmap));
REQUIRE(key != NULL && keysize > 0 && keysize <= UINT16_MAX);
REQUIRE(key != NULL && keysize <= UINT16_MAX);
hashmap_node_t *node;
isc_result_t result = ISC_R_NOTFOUND;
@ -600,7 +599,7 @@ isc_result_t
isc_hashmap_add(isc_hashmap_t *hashmap, const uint32_t *hashvalp,
const void *key, uint32_t keysize, void *value) {
REQUIRE(ISC_HASHMAP_VALID(hashmap));
REQUIRE(key != NULL && keysize > 0 && keysize <= UINT16_MAX);
REQUIRE(key != NULL && keysize <= UINT16_MAX);
isc_result_t result;
uint32_t hashval = (hashvalp != NULL)

View file

@ -351,6 +351,30 @@ ISC_RUN_TEST_IMPL(isc_hashmap_iterator) {
return;
}
ISC_RUN_TEST_IMPL(isc_hashmap_hash_zero_length) {
isc_hashmap_t *hashmap = NULL;
uint32_t hashval;
bool again = false;
again:
isc_hashmap_create(mctx, 1, ISC_HASHMAP_CASE_SENSITIVE, &hashmap);
hashval = isc_hashmap_hash(hashmap, "", 0);
isc_hashmap_destroy(&hashmap);
if (hashval == 0 && !again) {
/*
* We could be extremely unlock and the siphash could hash the
* zero length string to 0, so try one more time.
*/
again = true;
goto again;
}
assert_int_not_equal(hashval, 0);
}
ISC_RUN_TEST_IMPL(isc_hashmap_case) {
isc_result_t result;
isc_hashmap_t *hashmap = NULL;
@ -401,6 +425,7 @@ ISC_RUN_TEST_IMPL(isc_hashmap_case) {
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY(isc_hashmap_hash_zero_length)
ISC_TEST_ENTRY(isc_hashmap_case)
ISC_TEST_ENTRY(isc_hashmap_1_120)
ISC_TEST_ENTRY(isc_hashmap_6_1000)