Fix undefined function pointer casts in LHASH.

Bug: chromium:785442
Change-Id: I516e42684b913dc0de778dd9134f1ca108c04dfc
Reviewed-on: https://boringssl-review.googlesource.com/c/32120
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2018-09-24 14:43:16 -05:00 committed by CQ bot account: commit-bot@chromium.org
parent 1eff9482ca
commit b68b832238
2 changed files with 94 additions and 39 deletions

View File

@ -139,15 +139,17 @@ size_t lh_num_items(const _LHASH *lh) { return lh->num_items; }
// not found, it returns a pointer that points to a NULL pointer. If |out_hash|
// is not NULL, then it also puts the hash value of |data| in |*out_hash|.
static LHASH_ITEM **get_next_ptr_and_hash(const _LHASH *lh, uint32_t *out_hash,
const void *data) {
const uint32_t hash = lh->hash(data);
const void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func) {
const uint32_t hash = call_hash_func(lh->hash, data);
if (out_hash != NULL) {
*out_hash = hash;
}
LHASH_ITEM **ret = &lh->buckets[hash % lh->num_buckets];
for (LHASH_ITEM *cur = *ret; cur != NULL; cur = *ret) {
if (lh->comp(cur->data, data) == 0) {
if (call_cmp_func(lh->comp, cur->data, data) == 0) {
break;
}
ret = &cur->next;
@ -173,8 +175,11 @@ static LHASH_ITEM **get_next_ptr_by_key(const _LHASH *lh, const void *key,
return ret;
}
void *lh_retrieve(const _LHASH *lh, const void *data) {
LHASH_ITEM **next_ptr = get_next_ptr_and_hash(lh, NULL, data);
void *lh_retrieve(const _LHASH *lh, const void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func) {
LHASH_ITEM **next_ptr =
get_next_ptr_and_hash(lh, NULL, data, call_hash_func, call_cmp_func);
return *next_ptr == NULL ? NULL : (*next_ptr)->data;
}
@ -247,12 +252,15 @@ static void lh_maybe_resize(_LHASH *lh) {
}
}
int lh_insert(_LHASH *lh, void **old_data, void *data) {
int lh_insert(_LHASH *lh, void **old_data, void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func) {
uint32_t hash;
LHASH_ITEM **next_ptr, *item;
*old_data = NULL;
next_ptr = get_next_ptr_and_hash(lh, &hash, data);
next_ptr =
get_next_ptr_and_hash(lh, &hash, data, call_hash_func, call_cmp_func);
if (*next_ptr != NULL) {
@ -279,10 +287,13 @@ int lh_insert(_LHASH *lh, void **old_data, void *data) {
return 1;
}
void *lh_delete(_LHASH *lh, const void *data) {
void *lh_delete(_LHASH *lh, const void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func) {
LHASH_ITEM **next_ptr, *item, *ret;
next_ptr = get_next_ptr_and_hash(lh, NULL, data);
next_ptr =
get_next_ptr_and_hash(lh, NULL, data, call_hash_func, call_cmp_func);
if (*next_ptr == NULL) {
// No such element.
@ -300,8 +311,7 @@ void *lh_delete(_LHASH *lh, const void *data) {
return ret;
}
static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *),
void (*arg_func)(void *, void *), void *arg) {
void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), void *arg) {
if (lh == NULL) {
return;
}
@ -315,11 +325,7 @@ static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *),
LHASH_ITEM *next;
for (LHASH_ITEM *cur = lh->buckets[i]; cur != NULL; cur = next) {
next = cur->next;
if (arg_func) {
arg_func(cur->data, arg);
} else {
no_arg_func(cur->data);
}
func(cur->data, arg);
}
}
@ -333,14 +339,6 @@ static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *),
lh_maybe_resize(lh);
}
void lh_doall(_LHASH *lh, void (*func)(void *)) {
lh_doall_internal(lh, func, NULL, NULL);
}
void lh_doall_arg(_LHASH *lh, void (*func)(void *, void *), void *arg) {
lh_doall_internal(lh, NULL, func, arg);
}
uint32_t lh_strhash(const char *c) {
if (c == NULL) {
return 0;

View File

@ -104,11 +104,22 @@ typedef struct lhash_item_st {
// equal, to zero depending on whether |*a| is equal, or not equal to |*b|,
// respectively. Note the difference between this and |stack_cmp_func| in that
// this takes pointers to the objects directly.
//
// This function's actual type signature is int (*)(const T*, const T*). The
// low-level |lh_*| functions will be passed a type-specific wrapper to call it
// correctly.
typedef int (*lhash_cmp_func)(const void *a, const void *b);
typedef int (*lhash_cmp_func_helper)(lhash_cmp_func func, const void *a,
const void *b);
// lhash_hash_func is a function that maps an object to a uniformly distributed
// uint32_t.
//
// This function's actual type signature is uint32_t (*)(const T*). The
// low-level |lh_*| functions will be passed a type-specific wrapper to call it
// correctly.
typedef uint32_t (*lhash_hash_func)(const void *a);
typedef uint32_t (*lhash_hash_func_helper)(lhash_hash_func func, const void *a);
typedef struct lhash_st _LHASH;
@ -124,7 +135,9 @@ OPENSSL_EXPORT size_t lh_num_items(const _LHASH *lh);
// lh_retrieve finds an element equal to |data| in the hash table and returns
// it. If no such element exists, it returns NULL.
OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data);
OPENSSL_EXPORT void *lh_retrieve(const _LHASH *lh, const void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func);
// lh_retrieve_key finds an element matching |key|, given the specified hash and
// comparison function. This differs from |lh_retrieve| in that the key may be a
@ -140,15 +153,15 @@ OPENSSL_EXPORT void *lh_retrieve_key(const _LHASH *lh, const void *key,
// will be set to that value and it will be replaced. Otherwise, or in the
// event of an error, |*old_data| will be set to NULL. It returns one on
// success or zero in the case of an allocation error.
OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data);
OPENSSL_EXPORT int lh_insert(_LHASH *lh, void **old_data, void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func);
// lh_delete removes an element equal to |data| from the hash table and returns
// it. If no such element is found, it returns NULL.
OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data);
// lh_doall calls |func| on each element of the hash table.
// TODO(fork): rename this
OPENSSL_EXPORT void lh_doall(_LHASH *lh, void (*func)(void *));
OPENSSL_EXPORT void *lh_delete(_LHASH *lh, const void *data,
lhash_hash_func_helper call_hash_func,
lhash_cmp_func_helper call_cmp_func);
// lh_doall_arg calls |func| on each element of the hash table and also passes
// |arg| as the second argument.
@ -166,6 +179,16 @@ OPENSSL_EXPORT uint32_t lh_strhash(const char *c);
typedef int (*lhash_##type##_cmp_func)(const type *, const type *); \
typedef uint32_t (*lhash_##type##_hash_func)(const type *); \
\
OPENSSL_INLINE int lh_##type##_call_cmp_func(lhash_cmp_func func, \
const void *a, const void *b) { \
return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b); \
} \
\
OPENSSL_INLINE uint32_t lh_##type##_call_hash_func(lhash_hash_func func, \
const void *a) { \
return ((lhash_##type##_hash_func)func)((const type *)a); \
} \
\
OPENSSL_INLINE LHASH_OF(type) * \
lh_##type##_new(lhash_##type##_hash_func hash, \
lhash_##type##_cmp_func comp) { \
@ -183,38 +206,72 @@ OPENSSL_EXPORT uint32_t lh_strhash(const char *c);
\
OPENSSL_INLINE type *lh_##type##_retrieve(const LHASH_OF(type) *lh, \
const type *data) { \
return (type *)lh_retrieve((const _LHASH *)lh, data); \
return (type *)lh_retrieve((const _LHASH *)lh, data, \
lh_##type##_call_hash_func, \
lh_##type##_call_cmp_func); \
} \
\
typedef struct { \
int (*cmp_key)(const void *key, const type *value); \
const void *key; \
} LHASH_CMP_KEY_##type; \
\
OPENSSL_INLINE int lh_##type##_call_cmp_key(const void *key, \
const void *value) { \
const LHASH_CMP_KEY_##type *cb = (const LHASH_CMP_KEY_##type *)key; \
return cb->cmp_key(cb->key, (const type *)value); \
} \
\
OPENSSL_INLINE type *lh_##type##_retrieve_key( \
const LHASH_OF(type) *lh, const void *key, uint32_t key_hash, \
int (*cmp_key)(const void *key, const type *value)) { \
return (type *)lh_retrieve_key( \
(const _LHASH *)lh, key, key_hash, \
(int (*)(const void *, const void *))cmp_key); \
LHASH_CMP_KEY_##type cb = {cmp_key, key}; \
return (type *)lh_retrieve_key((const _LHASH *)lh, &cb, key_hash, \
lh_##type##_call_cmp_key); \
} \
\
OPENSSL_INLINE int lh_##type##_insert(LHASH_OF(type) *lh, type **old_data, \
type *data) { \
void *old_data_void = NULL; \
int ret = lh_insert((_LHASH *)lh, &old_data_void, data); \
int ret = \
lh_insert((_LHASH *)lh, &old_data_void, data, \
lh_##type##_call_hash_func, lh_##type##_call_cmp_func); \
*old_data = (type *)old_data_void; \
return ret; \
} \
\
OPENSSL_INLINE type *lh_##type##_delete(LHASH_OF(type) *lh, \
const type *data) { \
return (type *)lh_delete((_LHASH *)lh, data); \
return (type *)lh_delete((_LHASH *)lh, data, lh_##type##_call_hash_func, \
lh_##type##_call_cmp_func); \
} \
\
typedef struct { \
void (*doall)(type *); \
void (*doall_arg)(type *, void *); \
void *arg; \
} LHASH_DOALL_##type; \
\
OPENSSL_INLINE void lh_##type##_call_doall(void *value, void *arg) { \
const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \
cb->doall((type *)value); \
} \
\
OPENSSL_INLINE void lh_##type##_call_doall_arg(void *value, void *arg) { \
const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg; \
cb->doall_arg((type *)value, cb->arg); \
} \
\
OPENSSL_INLINE void lh_##type##_doall(LHASH_OF(type) *lh, \
void (*func)(type *)) { \
lh_doall((_LHASH *)lh, (void (*)(void *))func); \
LHASH_DOALL_##type cb = {func, NULL, NULL}; \
lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall, &cb); \
} \
\
OPENSSL_INLINE void lh_##type##_doall_arg( \
LHASH_OF(type) *lh, void (*func)(type *, void *), void *arg) { \
lh_doall_arg((_LHASH *)lh, (void (*)(void *, void *))func, arg); \
LHASH_DOALL_##type cb = {NULL, func, arg}; \
lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb); \
}