Coverage Report

Created: 2025-06-11 06:41

/src/boringssl/crypto/lhash/internal.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H
16
#define OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H
17
18
#include <openssl/base.h>
19
20
#if defined(__cplusplus)
21
extern "C" {
22
#endif
23
24
25
// lhash is a traditional, chaining hash table that automatically expands and
26
// contracts as needed. One should not use the lh_* functions directly, rather
27
// use the type-safe macro wrappers:
28
//
29
// A hash table of a specific type of object has type |LHASH_OF(type)|. This
30
// can be defined (once) with |DEFINE_LHASH_OF(type)| and declared where needed
31
// with |DECLARE_LHASH_OF(type)|. For example:
32
//
33
//   struct foo {
34
//     int bar;
35
//   };
36
//
37
//   DEFINE_LHASH_OF(struct foo)
38
//
39
// Although note that the hash table will contain /pointers/ to |foo|.
40
//
41
// A macro will be defined for each of the |OPENSSL_lh_*| functions below. For
42
// |LHASH_OF(foo)|, the macros would be |lh_foo_new|, |lh_foo_num_items| etc.
43
//
44
// TODO(davidben): Now that this type is completely internal, this can just be a
45
// C++ template without any macros.
46
47
48
#define LHASH_OF(type) struct lhash_st_##type
49
#define DECLARE_LHASH_OF(type) LHASH_OF(type);
50
51
// lhash_cmp_func is a comparison function that returns a value equal, or not
52
// equal, to zero depending on whether |*a| is equal, or not equal to |*b|,
53
// respectively. Note the difference between this and |stack_cmp_func| in that
54
// this takes pointers to the objects directly.
55
//
56
// This function's actual type signature is int (*)(const T*, const T*). The
57
// low-level |lh_*| functions will be passed a type-specific wrapper to call it
58
// correctly.
59
typedef int (*lhash_cmp_func)(const void *a, const void *b);
60
typedef int (*lhash_cmp_func_helper)(lhash_cmp_func func, const void *a,
61
                                     const void *b);
62
63
// lhash_hash_func is a function that maps an object to a uniformly distributed
64
// uint32_t.
65
//
66
// This function's actual type signature is uint32_t (*)(const T*). The
67
// low-level |lh_*| functions will be passed a type-specific wrapper to call it
68
// correctly.
69
typedef uint32_t (*lhash_hash_func)(const void *a);
70
typedef uint32_t (*lhash_hash_func_helper)(lhash_hash_func func, const void *a);
71
72
typedef struct lhash_st _LHASH;
73
74
// OPENSSL_lh_new returns a new, empty hash table or NULL on error.
75
OPENSSL_EXPORT _LHASH *OPENSSL_lh_new(lhash_hash_func hash,
76
                                      lhash_cmp_func comp);
77
78
// OPENSSL_lh_free frees the hash table itself but none of the elements. See
79
// |OPENSSL_lh_doall|.
80
OPENSSL_EXPORT void OPENSSL_lh_free(_LHASH *lh);
81
82
// OPENSSL_lh_num_items returns the number of items in |lh|.
83
OPENSSL_EXPORT size_t OPENSSL_lh_num_items(const _LHASH *lh);
84
85
// OPENSSL_lh_retrieve finds an element equal to |data| in the hash table and
86
// returns it. If no such element exists, it returns NULL.
87
OPENSSL_EXPORT void *OPENSSL_lh_retrieve(const _LHASH *lh, const void *data,
88
                                         lhash_hash_func_helper call_hash_func,
89
                                         lhash_cmp_func_helper call_cmp_func);
90
91
// OPENSSL_lh_retrieve_key finds an element matching |key|, given the specified
92
// hash and comparison function. This differs from |OPENSSL_lh_retrieve| in that
93
// the key may be a different type than the values stored in |lh|. |key_hash|
94
// and |cmp_key| must be compatible with the functions passed into
95
// |OPENSSL_lh_new|.
96
OPENSSL_EXPORT void *OPENSSL_lh_retrieve_key(const _LHASH *lh, const void *key,
97
                                             uint32_t key_hash,
98
                                             int (*cmp_key)(const void *key,
99
                                                            const void *value));
100
101
// OPENSSL_lh_insert inserts |data| into the hash table. If an existing element
102
// is equal to |data| (with respect to the comparison function) then |*old_data|
103
// will be set to that value and it will be replaced. Otherwise, or in the
104
// event of an error, |*old_data| will be set to NULL. It returns one on
105
// success or zero in the case of an allocation error.
106
OPENSSL_EXPORT int OPENSSL_lh_insert(_LHASH *lh, void **old_data, void *data,
107
                                     lhash_hash_func_helper call_hash_func,
108
                                     lhash_cmp_func_helper call_cmp_func);
109
110
// OPENSSL_lh_delete removes an element equal to |data| from the hash table and
111
// returns it. If no such element is found, it returns NULL.
112
OPENSSL_EXPORT void *OPENSSL_lh_delete(_LHASH *lh, const void *data,
113
                                       lhash_hash_func_helper call_hash_func,
114
                                       lhash_cmp_func_helper call_cmp_func);
115
116
// OPENSSL_lh_doall_arg calls |func| on each element of the hash table and also
117
// passes |arg| as the second argument.
118
// TODO(fork): rename this
119
OPENSSL_EXPORT void OPENSSL_lh_doall_arg(_LHASH *lh,
120
                                         void (*func)(void *, void *),
121
                                         void *arg);
122
123
#define DEFINE_LHASH_OF(type)                                                  \
124
  /* We disable MSVC C4191 in this macro, which warns when pointers are cast   \
125
   * to the wrong type. While the cast itself is valid, it is often a bug      \
126
   * because calling it through the cast is UB. However, we never actually     \
127
   * call functions as |lhash_cmp_func|. The type is just a type-erased        \
128
   * function pointer. (C does not guarantee function pointers fit in          \
129
   * |void*|, and GCC will warn on this.) Thus we just disable the false       \
130
   * positive warning. */                                                      \
131
  OPENSSL_MSVC_PRAGMA(warning(push))                                           \
132
  OPENSSL_MSVC_PRAGMA(warning(disable : 4191))                                 \
133
                                                                               \
134
  DECLARE_LHASH_OF(type)                                                       \
135
                                                                               \
136
  typedef int (*lhash_##type##_cmp_func)(const type *, const type *);          \
137
  typedef uint32_t (*lhash_##type##_hash_func)(const type *);                  \
138
                                                                               \
139
  inline int lh_##type##_call_cmp_func(lhash_cmp_func func, const void *a,     \
140
502k
                                       const void *b) {                        \
141
502k
    return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b);  \
142
502k
  }                                                                            \
lh_CONF_SECTION_call_cmp_func
Line
Count
Source
140
473k
                                       const void *b) {                        \
141
473k
    return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b);  \
142
473k
  }                                                                            \
lh_CONF_VALUE_call_cmp_func
Line
Count
Source
140
29.0k
                                       const void *b) {                        \
141
29.0k
    return ((lhash_##type##_cmp_func)func)((const type *)a, (const type *)b);  \
142
29.0k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_call_cmp_func(int (*)(void const*, void const*), void const*, void const*)
Unexecuted instantiation: lh_ASN1_OBJECT_call_cmp_func(int (*)(void const*, void const*), void const*, void const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_call_cmp_func
143
                                                                               \
144
  inline uint32_t lh_##type##_call_hash_func(lhash_hash_func func,             \
145
519k
                                             const void *a) {                  \
146
519k
    return ((lhash_##type##_hash_func)func)((const type *)a);                  \
147
519k
  }                                                                            \
lh_CONF_SECTION_call_hash_func
Line
Count
Source
145
486k
                                             const void *a) {                  \
146
486k
    return ((lhash_##type##_hash_func)func)((const type *)a);                  \
147
486k
  }                                                                            \
lh_CONF_VALUE_call_hash_func
Line
Count
Source
145
33.5k
                                             const void *a) {                  \
146
33.5k
    return ((lhash_##type##_hash_func)func)((const type *)a);                  \
147
33.5k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_call_hash_func(unsigned int (*)(void const*), void const*)
Unexecuted instantiation: lh_ASN1_OBJECT_call_hash_func(unsigned int (*)(void const*), void const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_call_hash_func
148
                                                                               \
149
  inline LHASH_OF(type) *lh_##type##_new(lhash_##type##_hash_func hash,        \
150
24.7k
                                         lhash_##type##_cmp_func comp) {       \
151
24.7k
    return (LHASH_OF(type) *)OPENSSL_lh_new((lhash_hash_func)hash,             \
152
24.7k
                                            (lhash_cmp_func)comp);             \
153
24.7k
  }                                                                            \
lh_CONF_SECTION_new
Line
Count
Source
150
12.3k
                                         lhash_##type##_cmp_func comp) {       \
151
12.3k
    return (LHASH_OF(type) *)OPENSSL_lh_new((lhash_hash_func)hash,             \
152
12.3k
                                            (lhash_cmp_func)comp);             \
153
12.3k
  }                                                                            \
lh_CONF_VALUE_new
Line
Count
Source
150
12.3k
                                         lhash_##type##_cmp_func comp) {       \
151
12.3k
    return (LHASH_OF(type) *)OPENSSL_lh_new((lhash_hash_func)hash,             \
152
12.3k
                                            (lhash_cmp_func)comp);             \
153
12.3k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_new(unsigned int (*)(ASN1_STRING_TABLE const*), int (*)(ASN1_STRING_TABLE const*, ASN1_STRING_TABLE const*))
Unexecuted instantiation: lh_ASN1_OBJECT_new(unsigned int (*)(asn1_object_st const*), int (*)(asn1_object_st const*, asn1_object_st const*))
Unexecuted instantiation: lh_CRYPTO_BUFFER_new
154
                                                                               \
155
24.7k
  inline void lh_##type##_free(LHASH_OF(type) *lh) {                           \
156
24.7k
    OPENSSL_lh_free((_LHASH *)lh);                                             \
157
24.7k
  }                                                                            \
lh_CONF_SECTION_free
Line
Count
Source
155
12.3k
  inline void lh_##type##_free(LHASH_OF(type) *lh) {                           \
156
12.3k
    OPENSSL_lh_free((_LHASH *)lh);                                             \
157
12.3k
  }                                                                            \
lh_CONF_VALUE_free
Line
Count
Source
155
12.3k
  inline void lh_##type##_free(LHASH_OF(type) *lh) {                           \
156
12.3k
    OPENSSL_lh_free((_LHASH *)lh);                                             \
157
12.3k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_free(lhash_st_ASN1_STRING_TABLE*)
Unexecuted instantiation: lh_ASN1_OBJECT_free(lhash_st_ASN1_OBJECT*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_free
158
                                                                               \
159
0
  inline size_t lh_##type##_num_items(const LHASH_OF(type) *lh) {              \
160
0
    return OPENSSL_lh_num_items((const _LHASH *)lh);                           \
161
0
  }                                                                            \
Unexecuted instantiation: lh_CONF_SECTION_num_items
Unexecuted instantiation: lh_CONF_VALUE_num_items
Unexecuted instantiation: lh_ASN1_STRING_TABLE_num_items(lhash_st_ASN1_STRING_TABLE const*)
Unexecuted instantiation: lh_ASN1_OBJECT_num_items(lhash_st_ASN1_OBJECT const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_num_items
162
                                                                               \
163
  inline type *lh_##type##_retrieve(const LHASH_OF(type) *lh,                  \
164
464k
                                    const type *data) {                        \
165
464k
    return (type *)OPENSSL_lh_retrieve((const _LHASH *)lh, data,               \
166
464k
                                       lh_##type##_call_hash_func,             \
167
464k
                                       lh_##type##_call_cmp_func);             \
168
464k
  }                                                                            \
lh_CONF_SECTION_retrieve
Line
Count
Source
164
464k
                                    const type *data) {                        \
165
464k
    return (type *)OPENSSL_lh_retrieve((const _LHASH *)lh, data,               \
166
464k
                                       lh_##type##_call_hash_func,             \
167
464k
                                       lh_##type##_call_cmp_func);             \
168
464k
  }                                                                            \
Unexecuted instantiation: lh_CONF_VALUE_retrieve
Unexecuted instantiation: lh_ASN1_STRING_TABLE_retrieve(lhash_st_ASN1_STRING_TABLE const*, ASN1_STRING_TABLE const*)
Unexecuted instantiation: lh_ASN1_OBJECT_retrieve(lhash_st_ASN1_OBJECT const*, asn1_object_st const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_retrieve
169
                                                                               \
170
  typedef struct {                                                             \
171
    int (*cmp_key)(const void *key, const type *value);                        \
172
    const void *key;                                                           \
173
  } LHASH_CMP_KEY_##type;                                                      \
174
                                                                               \
175
0
  inline int lh_##type##_call_cmp_key(const void *key, const void *value) {    \
176
0
    const LHASH_CMP_KEY_##type *cb = (const LHASH_CMP_KEY_##type *)key;        \
177
0
    return cb->cmp_key(cb->key, (const type *)value);                          \
178
0
  }                                                                            \
Unexecuted instantiation: lh_CONF_SECTION_call_cmp_key
Unexecuted instantiation: lh_CONF_VALUE_call_cmp_key
Unexecuted instantiation: lh_ASN1_STRING_TABLE_call_cmp_key(void const*, void const*)
Unexecuted instantiation: lh_ASN1_OBJECT_call_cmp_key(void const*, void const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_call_cmp_key
179
                                                                               \
180
  inline type *lh_##type##_retrieve_key(                                       \
181
      const LHASH_OF(type) *lh, const void *key, uint32_t key_hash,            \
182
0
      int (*cmp_key)(const void *key, const type *value)) {                    \
183
0
    LHASH_CMP_KEY_##type cb = {cmp_key, key};                                  \
184
0
    return (type *)OPENSSL_lh_retrieve_key((const _LHASH *)lh, &cb, key_hash,  \
185
0
                                           lh_##type##_call_cmp_key);          \
186
0
  }                                                                            \
Unexecuted instantiation: lh_CONF_SECTION_retrieve_key
Unexecuted instantiation: lh_CONF_VALUE_retrieve_key
Unexecuted instantiation: lh_ASN1_STRING_TABLE_retrieve_key(lhash_st_ASN1_STRING_TABLE const*, void const*, unsigned int, int (*)(void const*, ASN1_STRING_TABLE const*))
Unexecuted instantiation: lh_ASN1_OBJECT_retrieve_key(lhash_st_ASN1_OBJECT const*, void const*, unsigned int, int (*)(void const*, asn1_object_st const*))
Unexecuted instantiation: lh_CRYPTO_BUFFER_retrieve_key
187
                                                                               \
188
  inline int lh_##type##_insert(LHASH_OF(type) *lh, type **old_data,           \
189
54.8k
                                type *data) {                                  \
190
54.8k
    void *old_data_void = NULL;                                                \
191
54.8k
    int ret = OPENSSL_lh_insert((_LHASH *)lh, &old_data_void, data,            \
192
54.8k
                                lh_##type##_call_hash_func,                    \
193
54.8k
                                lh_##type##_call_cmp_func);                    \
194
54.8k
    *old_data = (type *)old_data_void;                                         \
195
54.8k
    return ret;                                                                \
196
54.8k
  }                                                                            \
lh_CONF_SECTION_insert
Line
Count
Source
189
21.3k
                                type *data) {                                  \
190
21.3k
    void *old_data_void = NULL;                                                \
191
21.3k
    int ret = OPENSSL_lh_insert((_LHASH *)lh, &old_data_void, data,            \
192
21.3k
                                lh_##type##_call_hash_func,                    \
193
21.3k
                                lh_##type##_call_cmp_func);                    \
194
21.3k
    *old_data = (type *)old_data_void;                                         \
195
21.3k
    return ret;                                                                \
196
21.3k
  }                                                                            \
lh_CONF_VALUE_insert
Line
Count
Source
189
33.5k
                                type *data) {                                  \
190
33.5k
    void *old_data_void = NULL;                                                \
191
33.5k
    int ret = OPENSSL_lh_insert((_LHASH *)lh, &old_data_void, data,            \
192
33.5k
                                lh_##type##_call_hash_func,                    \
193
33.5k
                                lh_##type##_call_cmp_func);                    \
194
33.5k
    *old_data = (type *)old_data_void;                                         \
195
33.5k
    return ret;                                                                \
196
33.5k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_insert(lhash_st_ASN1_STRING_TABLE*, ASN1_STRING_TABLE**, ASN1_STRING_TABLE*)
Unexecuted instantiation: lh_ASN1_OBJECT_insert(lhash_st_ASN1_OBJECT*, asn1_object_st**, asn1_object_st*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_insert
197
                                                                               \
198
0
  inline type *lh_##type##_delete(LHASH_OF(type) *lh, const type *data) {      \
199
0
    return (type *)OPENSSL_lh_delete((_LHASH *)lh, data,                       \
200
0
                                     lh_##type##_call_hash_func,               \
201
0
                                     lh_##type##_call_cmp_func);               \
202
0
  }                                                                            \
Unexecuted instantiation: lh_CONF_SECTION_delete
Unexecuted instantiation: lh_CONF_VALUE_delete
Unexecuted instantiation: lh_ASN1_STRING_TABLE_delete(lhash_st_ASN1_STRING_TABLE*, ASN1_STRING_TABLE const*)
Unexecuted instantiation: lh_ASN1_OBJECT_delete(lhash_st_ASN1_OBJECT*, asn1_object_st const*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_delete
203
                                                                               \
204
  typedef struct {                                                             \
205
    void (*doall_arg)(type *, void *);                                         \
206
    void *arg;                                                                 \
207
  } LHASH_DOALL_##type;                                                        \
208
                                                                               \
209
51.2k
  inline void lh_##type##_call_doall_arg(void *value, void *arg) {             \
210
51.2k
    const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg;            \
211
51.2k
    cb->doall_arg((type *)value, cb->arg);                                     \
212
51.2k
  }                                                                            \
lh_CONF_SECTION_call_doall_arg
Line
Count
Source
209
21.3k
  inline void lh_##type##_call_doall_arg(void *value, void *arg) {             \
210
21.3k
    const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg;            \
211
21.3k
    cb->doall_arg((type *)value, cb->arg);                                     \
212
21.3k
  }                                                                            \
lh_CONF_VALUE_call_doall_arg
Line
Count
Source
209
29.9k
  inline void lh_##type##_call_doall_arg(void *value, void *arg) {             \
210
29.9k
    const LHASH_DOALL_##type *cb = (const LHASH_DOALL_##type *)arg;            \
211
29.9k
    cb->doall_arg((type *)value, cb->arg);                                     \
212
29.9k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_call_doall_arg(void*, void*)
Unexecuted instantiation: lh_ASN1_OBJECT_call_doall_arg(void*, void*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_call_doall_arg
213
                                                                               \
214
  inline void lh_##type##_doall_arg(LHASH_OF(type) *lh,                        \
215
24.7k
                                    void (*func)(type *, void *), void *arg) { \
216
24.7k
    LHASH_DOALL_##type cb = {func, arg};                                       \
217
24.7k
    OPENSSL_lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb);       \
218
24.7k
  }                                                                            \
lh_CONF_SECTION_doall_arg
Line
Count
Source
215
12.3k
                                    void (*func)(type *, void *), void *arg) { \
216
12.3k
    LHASH_DOALL_##type cb = {func, arg};                                       \
217
12.3k
    OPENSSL_lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb);       \
218
12.3k
  }                                                                            \
lh_CONF_VALUE_doall_arg
Line
Count
Source
215
12.3k
                                    void (*func)(type *, void *), void *arg) { \
216
12.3k
    LHASH_DOALL_##type cb = {func, arg};                                       \
217
12.3k
    OPENSSL_lh_doall_arg((_LHASH *)lh, lh_##type##_call_doall_arg, &cb);       \
218
12.3k
  }                                                                            \
Unexecuted instantiation: lh_ASN1_STRING_TABLE_doall_arg(lhash_st_ASN1_STRING_TABLE*, void (*)(ASN1_STRING_TABLE*, void*), void*)
Unexecuted instantiation: lh_ASN1_OBJECT_doall_arg(lhash_st_ASN1_OBJECT*, void (*)(asn1_object_st*, void*), void*)
Unexecuted instantiation: lh_CRYPTO_BUFFER_doall_arg
219
                                                                               \
220
  OPENSSL_MSVC_PRAGMA(warning(pop))
221
222
223
#if defined(__cplusplus)
224
}  // extern C
225
#endif
226
227
#endif  // OPENSSL_HEADER_CRYPTO_LHASH_INTERNAL_H