Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/objects/o_names.c
Line
Count
Source (jump to first uncovered line)
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
#include <openssl/err.h>
6
#include <openssl/lhash.h>
7
#include <openssl/objects.h>
8
#include <openssl/safestack.h>
9
#include <openssl/e_os2.h>
10
11
/*
12
 * Later versions of DEC C has started to add lnkage information to certain
13
 * functions, which makes it tricky to use them as values to regular function
14
 * pointers.  One way is to define a macro that takes care of casting them
15
 * correctly.
16
 */
17
#ifdef OPENSSL_SYS_VMS_DECC
18
# define OPENSSL_strcmp (int (*)(const char *,const char *))strcmp
19
#else
20
0
# define OPENSSL_strcmp strcmp
21
#endif
22
23
/*
24
 * I use the ex_data stuff to manage the identifiers for the obj_name_types
25
 * that applications may define.  I only really use the free function field.
26
 */
27
DECLARE_LHASH_OF(OBJ_NAME);
28
static LHASH_OF(OBJ_NAME) *names_lh = NULL;
29
static int names_type_num = OBJ_NAME_TYPE_NUM;
30
31
typedef struct name_funcs_st {
32
    unsigned long (*hash_func) (const char *name);
33
    int (*cmp_func) (const char *a, const char *b);
34
    void (*free_func) (const char *, int, const char *);
35
} NAME_FUNCS;
36
37
DECLARE_STACK_OF(NAME_FUNCS)
38
IMPLEMENT_STACK_OF(NAME_FUNCS)
39
40
static STACK_OF(NAME_FUNCS) *name_funcs_stack;
41
42
/*
43
 * The LHASH callbacks now use the raw "void *" prototypes and do
44
 * per-variable casting in the functions. This prevents function pointer
45
 * casting without the need for macro-generated wrapper functions.
46
 */
47
48
/* static unsigned long obj_name_hash(OBJ_NAME *a); */
49
static unsigned long obj_name_hash(const void *a_void);
50
/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
51
static int obj_name_cmp(const void *a_void, const void *b_void);
52
53
static IMPLEMENT_LHASH_HASH_FN(obj_name, OBJ_NAME)
54
static IMPLEMENT_LHASH_COMP_FN(obj_name, OBJ_NAME)
55
56
int OBJ_NAME_init(void)
57
19
{
58
19
    if (names_lh != NULL)
59
0
        return (1);
60
19
    MemCheck_off();
61
19
    names_lh = lh_OBJ_NAME_new();
62
19
    MemCheck_on();
63
19
    return (names_lh != NULL);
64
19
}
65
66
int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *),
67
                       int (*cmp_func) (const char *, const char *),
68
                       void (*free_func) (const char *, int, const char *))
69
0
{
70
0
    int ret;
71
0
    int i;
72
0
    NAME_FUNCS *name_funcs;
73
74
0
    if (name_funcs_stack == NULL) {
75
0
        MemCheck_off();
76
0
        name_funcs_stack = sk_NAME_FUNCS_new_null();
77
0
        MemCheck_on();
78
0
    }
79
0
    if (name_funcs_stack == NULL) {
80
        /* ERROR */
81
0
        return (0);
82
0
    }
83
0
    ret = names_type_num;
84
0
    names_type_num++;
85
0
    for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) {
86
0
        MemCheck_off();
87
0
        name_funcs = OPENSSL_malloc(sizeof(NAME_FUNCS));
88
0
        MemCheck_on();
89
0
        if (!name_funcs) {
90
0
            OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX, ERR_R_MALLOC_FAILURE);
91
0
            return (0);
92
0
        }
93
0
        name_funcs->hash_func = lh_strhash;
94
0
        name_funcs->cmp_func = OPENSSL_strcmp;
95
0
        name_funcs->free_func = 0; /* NULL is often declared to * ((void
96
                                    * *)0), which according * to Compaq C is
97
                                    * not really * compatible with a function
98
                                    * * pointer.  -- Richard Levitte */
99
0
        MemCheck_off();
100
0
        sk_NAME_FUNCS_push(name_funcs_stack, name_funcs);
101
0
        MemCheck_on();
102
0
    }
103
0
    name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
104
0
    if (hash_func != NULL)
105
0
        name_funcs->hash_func = hash_func;
106
0
    if (cmp_func != NULL)
107
0
        name_funcs->cmp_func = cmp_func;
108
0
    if (free_func != NULL)
109
0
        name_funcs->free_func = free_func;
110
0
    return (ret);
111
0
}
112
113
/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
114
static int obj_name_cmp(const void *a_void, const void *b_void)
115
9.30k
{
116
9.30k
    int ret;
117
9.30k
    const OBJ_NAME *a = (const OBJ_NAME *)a_void;
118
9.30k
    const OBJ_NAME *b = (const OBJ_NAME *)b_void;
119
120
9.30k
    ret = a->type - b->type;
121
9.30k
    if (ret == 0) {
122
9.30k
        if ((name_funcs_stack != NULL)
123
9.30k
            && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) {
124
0
            ret = sk_NAME_FUNCS_value(name_funcs_stack,
125
0
                                      a->type)->cmp_func(a->name, b->name);
126
0
        } else
127
9.30k
            ret = strcmp(a->name, b->name);
128
9.30k
    }
129
9.30k
    return (ret);
130
9.30k
}
131
132
/* static unsigned long obj_name_hash(OBJ_NAME *a) */
133
static unsigned long obj_name_hash(const void *a_void)
134
14.8k
{
135
14.8k
    unsigned long ret;
136
14.8k
    const OBJ_NAME *a = (const OBJ_NAME *)a_void;
137
138
14.8k
    if ((name_funcs_stack != NULL)
139
14.8k
        && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) {
140
0
        ret =
141
0
            sk_NAME_FUNCS_value(name_funcs_stack,
142
0
                                a->type)->hash_func(a->name);
143
14.8k
    } else {
144
14.8k
        ret = lh_strhash(a->name);
145
14.8k
    }
146
14.8k
    ret ^= a->type;
147
14.8k
    return (ret);
148
14.8k
}
149
150
const char *OBJ_NAME_get(const char *name, int type)
151
4.09k
{
152
4.09k
    OBJ_NAME on, *ret;
153
4.09k
    int num = 0, alias;
154
155
4.09k
    if (name == NULL)
156
0
        return (NULL);
157
4.09k
    if ((names_lh == NULL) && !OBJ_NAME_init())
158
0
        return (NULL);
159
160
4.09k
    alias = type & OBJ_NAME_ALIAS;
161
4.09k
    type &= ~OBJ_NAME_ALIAS;
162
163
4.09k
    on.name = name;
164
4.09k
    on.type = type;
165
166
7.81k
    for (;;) {
167
7.81k
        ret = lh_OBJ_NAME_retrieve(names_lh, &on);
168
7.81k
        if (ret == NULL)
169
0
            return (NULL);
170
7.81k
        if ((ret->alias) && !alias) {
171
3.72k
            if (++num > 10)
172
0
                return (NULL);
173
3.72k
            on.name = ret->data;
174
4.09k
        } else {
175
4.09k
            return (ret->data);
176
4.09k
        }
177
7.81k
    }
178
4.09k
}
179
180
int OBJ_NAME_add(const char *name, int type, const char *data)
181
7.01k
{
182
7.01k
    OBJ_NAME *onp, *ret;
183
7.01k
    int alias;
184
185
7.01k
    if ((names_lh == NULL) && !OBJ_NAME_init())
186
0
        return (0);
187
188
7.01k
    alias = type & OBJ_NAME_ALIAS;
189
7.01k
    type &= ~OBJ_NAME_ALIAS;
190
191
7.01k
    onp = (OBJ_NAME *)OPENSSL_malloc(sizeof(OBJ_NAME));
192
7.01k
    if (onp == NULL) {
193
        /* ERROR */
194
0
        return 0;
195
0
    }
196
197
7.01k
    onp->name = name;
198
7.01k
    onp->alias = alias;
199
7.01k
    onp->type = type;
200
7.01k
    onp->data = data;
201
202
7.01k
    ret = lh_OBJ_NAME_insert(names_lh, onp);
203
7.01k
    if (ret != NULL) {
204
        /* free things */
205
1.48k
        if ((name_funcs_stack != NULL)
206
1.48k
            && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) {
207
            /*
208
             * XXX: I'm not sure I understand why the free function should
209
             * get three arguments... -- Richard Levitte
210
             */
211
0
            sk_NAME_FUNCS_value(name_funcs_stack,
212
0
                                ret->type)->free_func(ret->name, ret->type,
213
0
                                                      ret->data);
214
0
        }
215
1.48k
        OPENSSL_free(ret);
216
5.52k
    } else {
217
5.52k
        if (lh_OBJ_NAME_error(names_lh)) {
218
            /* ERROR */
219
0
            OPENSSL_free(onp);
220
0
            return 0;
221
0
        }
222
5.52k
    }
223
7.01k
    return 1;
224
7.01k
}
225
226
int OBJ_NAME_remove(const char *name, int type)
227
0
{
228
0
    OBJ_NAME on, *ret;
229
230
0
    if (names_lh == NULL)
231
0
        return (0);
232
233
0
    type &= ~OBJ_NAME_ALIAS;
234
0
    on.name = name;
235
0
    on.type = type;
236
0
    ret = lh_OBJ_NAME_delete(names_lh, &on);
237
0
    if (ret != NULL) {
238
        /* free things */
239
0
        if ((name_funcs_stack != NULL)
240
0
            && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) {
241
            /*
242
             * XXX: I'm not sure I understand why the free function should
243
             * get three arguments... -- Richard Levitte
244
             */
245
0
            sk_NAME_FUNCS_value(name_funcs_stack,
246
0
                                ret->type)->free_func(ret->name, ret->type,
247
0
                                                      ret->data);
248
0
        }
249
0
        OPENSSL_free(ret);
250
0
        return (1);
251
0
    } else
252
0
        return (0);
253
0
}
254
255
struct doall {
256
    int type;
257
    void (*fn) (const OBJ_NAME *, void *arg);
258
    void *arg;
259
};
260
261
static void do_all_fn_doall_arg(const OBJ_NAME *name, struct doall *d)
262
0
{
263
0
    if (name->type == d->type)
264
0
        d->fn(name, d->arg);
265
0
}
266
267
static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall)
268
269
void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg),
270
                     void *arg)
271
0
{
272
0
    struct doall d;
273
274
0
    d.type = type;
275
0
    d.fn = fn;
276
0
    d.arg = arg;
277
278
0
    lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn),
279
0
                          struct doall, &d);
280
0
}
281
282
struct doall_sorted {
283
    int type;
284
    int n;
285
    const OBJ_NAME **names;
286
};
287
288
static void do_all_sorted_fn(const OBJ_NAME *name, void *d_)
289
0
{
290
0
    struct doall_sorted *d = d_;
291
292
0
    if (name->type != d->type)
293
0
        return;
294
295
0
    d->names[d->n++] = name;
296
0
}
297
298
static int do_all_sorted_cmp(const void *n1_, const void *n2_)
299
0
{
300
0
    const OBJ_NAME *const *n1 = n1_;
301
0
    const OBJ_NAME *const *n2 = n2_;
302
303
0
    return strcmp((*n1)->name, (*n2)->name);
304
0
}
305
306
void OBJ_NAME_do_all_sorted(int type,
307
                            void (*fn) (const OBJ_NAME *, void *arg),
308
                            void *arg)
309
0
{
310
0
    struct doall_sorted d;
311
0
    int n;
312
313
0
    d.type = type;
314
0
    d.names =
315
0
        OPENSSL_malloc(lh_OBJ_NAME_num_items(names_lh) * sizeof *d.names);
316
    /* Really should return an error if !d.names...but its a void function! */
317
0
    if (d.names) {
318
0
        d.n = 0;
319
0
        OBJ_NAME_do_all(type, do_all_sorted_fn, &d);
320
321
0
        qsort((void *)d.names, d.n, sizeof *d.names, do_all_sorted_cmp);
322
323
0
        for (n = 0; n < d.n; ++n)
324
0
            fn(d.names[n], arg);
325
326
0
        OPENSSL_free((void *)d.names);
327
0
    }
328
0
}
329
330
static int free_type;
331
332
static void names_lh_free_doall(OBJ_NAME *onp)
333
0
{
334
0
    if (onp == NULL)
335
0
        return;
336
337
0
    if (free_type < 0 || free_type == onp->type)
338
0
        OBJ_NAME_remove(onp->name, onp->type);
339
0
}
340
341
static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME)
342
343
static void name_funcs_free(NAME_FUNCS *ptr)
344
0
{
345
0
    OPENSSL_free(ptr);
346
0
}
347
348
void OBJ_NAME_cleanup(int type)
349
0
{
350
0
    unsigned long down_load;
351
352
0
    if (names_lh == NULL)
353
0
        return;
354
355
0
    free_type = type;
356
0
    down_load = lh_OBJ_NAME_down_load(names_lh);
357
0
    lh_OBJ_NAME_down_load(names_lh) = 0;
358
359
0
    lh_OBJ_NAME_doall(names_lh, LHASH_DOALL_FN(names_lh_free));
360
0
    if (type < 0) {
361
0
        lh_OBJ_NAME_free(names_lh);
362
0
        sk_NAME_FUNCS_pop_free(name_funcs_stack, name_funcs_free);
363
0
        names_lh = NULL;
364
0
        name_funcs_stack = NULL;
365
0
    } else
366
0
        lh_OBJ_NAME_down_load(names_lh) = down_load;
367
0
}