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>
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
index e4fc3fd..98ee60a 100644
--- a/crypto/lhash/lhash.c
+++ b/crypto/lhash/lhash.c
@@ -139,15 +139,17 @@
// 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 @@
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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;
diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h
index 77ca493..c82bb8e 100644
--- a/include/openssl/lhash.h
+++ b/include/openssl/lhash.h
@@ -104,11 +104,22 @@
// 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 @@
// 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 @@
// 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 @@
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_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); \
}