Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/stack/stack.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include "internal/numbers.h"
13
#include "internal/safe_math.h"
14
#include <openssl/stack.h>
15
#include <errno.h>
16
#include <openssl/e_os2.h> /* For ossl_inline */
17
18
OSSL_SAFE_MATH_SIGNED(int, int)
19
20
/*
21
 * The initial number of nodes in the array.
22
 */
23
static const int min_nodes = 4;
24
static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX
25
    ? (int)(SIZE_MAX / sizeof(void *))
26
    : INT_MAX;
27
28
struct stack_st {
29
    int num;
30
    const void **data;
31
    int sorted;
32
    int num_alloc;
33
    OPENSSL_sk_compfunc comp;
34
    OPENSSL_sk_freefunc_thunk free_thunk;
35
};
36
37
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk,
38
    OPENSSL_sk_compfunc c)
39
0
{
40
0
    OPENSSL_sk_compfunc old = sk->comp;
41
42
0
    if (sk->comp != c && sk->num > 1)
43
0
        sk->sorted = 0;
44
0
    sk->comp = c;
45
46
0
    return old;
47
0
}
48
49
static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
50
    OPENSSL_sk_copyfunc copy_func,
51
    OPENSSL_sk_freefunc free_func)
52
1.26k
{
53
1.26k
    OPENSSL_STACK *ret;
54
1.26k
    int i;
55
56
1.26k
    if ((ret = OPENSSL_sk_new_null()) == NULL)
57
0
        goto err;
58
59
1.26k
    if (sk == NULL)
60
16
        goto done;
61
62
    /* direct structure assignment */
63
1.24k
    *ret = *sk;
64
1.24k
    ret->data = NULL;
65
1.24k
    ret->num_alloc = 0;
66
67
1.24k
    if (ret->num == 0)
68
0
        goto done; /* nothing to copy */
69
70
1.24k
    ret->num_alloc = ret->num > min_nodes ? ret->num : min_nodes;
71
1.24k
    ret->data = OPENSSL_calloc(ret->num_alloc, sizeof(*ret->data));
72
1.24k
    if (ret->data == NULL)
73
0
        goto err;
74
1.24k
    if (copy_func == NULL) {
75
1.24k
        memcpy(ret->data, sk->data, sizeof(*ret->data) * ret->num);
76
1.24k
    } else {
77
0
        for (i = 0; i < ret->num; ++i) {
78
0
            if (sk->data[i] == NULL)
79
0
                continue;
80
0
            if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
81
0
                while (--i >= 0)
82
0
                    if (ret->data[i] != NULL)
83
0
                        free_func((void *)ret->data[i]);
84
0
                goto err;
85
0
            }
86
0
        }
87
0
    }
88
89
1.26k
done:
90
1.26k
    return ret;
91
92
0
err:
93
0
    OPENSSL_sk_free(ret);
94
0
    return NULL;
95
1.24k
}
96
97
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
98
    OPENSSL_sk_copyfunc copy_func,
99
    OPENSSL_sk_freefunc free_func)
100
13
{
101
13
    return internal_copy(sk, copy_func, free_func);
102
13
}
103
104
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
105
1.24k
{
106
1.24k
    return internal_copy(sk, NULL, NULL);
107
1.24k
}
108
109
OPENSSL_STACK *OPENSSL_sk_new_null(void)
110
2.15k
{
111
2.15k
    return OPENSSL_sk_new_reserve(NULL, 0);
112
2.15k
}
113
114
OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
115
234
{
116
234
    return OPENSSL_sk_new_reserve(c, 0);
117
234
}
118
119
/*
120
 * Calculate the array growth based on the target size.
121
 *
122
 * The growth factor is a rational number and is defined by a numerator
123
 * and a denominator.  According to Andrew Koenig in his paper "Why Are
124
 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
125
 * than the golden ratio (1.618...).
126
 *
127
 * Considering only the Fibonacci ratios less than the golden ratio, the
128
 * number of steps from the minimum allocation to integer overflow is:
129
 *      factor  decimal    growths
130
 *       3/2     1.5          51
131
 *       8/5     1.6          45
132
 *      21/13    1.615...     44
133
 *
134
 * All larger factors have the same number of growths.
135
 *
136
 * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice.
137
 */
138
static ossl_inline int compute_growth(int target, int current)
139
58
{
140
58
    int err = 0;
141
142
116
    while (current < target) {
143
58
        if (current >= max_nodes)
144
0
            return 0;
145
146
58
        current = safe_muldiv_int(current, 8, 5, &err);
147
58
        if (err != 0)
148
0
            return 0;
149
58
        if (current >= max_nodes)
150
0
            current = max_nodes;
151
58
    }
152
58
    return current;
153
58
}
154
155
/* internal STACK storage allocation */
156
static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
157
2.24k
{
158
2.24k
    const void **tmpdata;
159
2.24k
    int num_alloc;
160
161
    /* Check to see the reservation isn't exceeding the hard limit */
162
2.24k
    if (n > max_nodes - st->num) {
163
0
        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
164
0
        return 0;
165
0
    }
166
167
    /* Figure out the new size */
168
2.24k
    num_alloc = st->num + n;
169
2.24k
    if (num_alloc < min_nodes)
170
1.56k
        num_alloc = min_nodes;
171
172
    /* If |st->data| allocation was postponed */
173
2.24k
    if (st->data == NULL) {
174
        /*
175
         * At this point, |st->num_alloc| and |st->num| are 0;
176
         * so |num_alloc| value is |n| or |min_nodes| if greater than |n|.
177
         */
178
891
        if ((st->data = OPENSSL_calloc(num_alloc, sizeof(void *))) == NULL)
179
0
            return 0;
180
891
        st->num_alloc = num_alloc;
181
891
        return 1;
182
891
    }
183
184
1.35k
    if (!exact) {
185
1.35k
        if (num_alloc <= st->num_alloc)
186
1.29k
            return 1;
187
58
        num_alloc = compute_growth(num_alloc, st->num_alloc);
188
58
        if (num_alloc == 0) {
189
0
            ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
190
0
            return 0;
191
0
        }
192
58
    } else if (num_alloc == st->num_alloc) {
193
0
        return 1;
194
0
    }
195
196
58
    tmpdata = OPENSSL_realloc_array((void *)st->data, num_alloc, sizeof(void *));
197
58
    if (tmpdata == NULL)
198
0
        return 0;
199
200
58
    st->data = tmpdata;
201
58
    st->num_alloc = num_alloc;
202
58
    return 1;
203
58
}
204
205
OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
206
2.38k
{
207
2.38k
    OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
208
209
2.38k
    if (st == NULL)
210
0
        return NULL;
211
212
2.38k
    st->comp = c;
213
2.38k
    st->sorted = 1; /* empty or single-element stack is considered sorted */
214
215
2.38k
    if (n <= 0)
216
2.38k
        return st;
217
218
0
    if (!sk_reserve(st, n, 1)) {
219
0
        OPENSSL_sk_free(st);
220
0
        return NULL;
221
0
    }
222
223
0
    return st;
224
0
}
225
226
int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
227
0
{
228
0
    if (st == NULL) {
229
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
230
0
        return 0;
231
0
    }
232
233
0
    if (n < 0)
234
0
        return 1;
235
0
    return sk_reserve(st, n, 1);
236
0
}
237
238
OPENSSL_STACK *OPENSSL_sk_set_thunks(OPENSSL_STACK *st, OPENSSL_sk_freefunc_thunk f_thunk)
239
547
{
240
547
    if (st != NULL)
241
481
        st->free_thunk = f_thunk;
242
243
547
    return st;
244
547
}
245
246
int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
247
2.24k
{
248
2.24k
    if (st == NULL) {
249
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
250
0
        return 0;
251
0
    }
252
2.24k
    if (st->num == max_nodes) {
253
0
        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
254
0
        return 0;
255
0
    }
256
257
2.24k
    if (!sk_reserve(st, 1, 0))
258
0
        return 0;
259
260
2.24k
    if ((loc >= st->num) || (loc < 0)) {
261
2.24k
        loc = st->num;
262
2.24k
        st->data[loc] = data;
263
2.24k
    } else {
264
0
        memmove(&st->data[loc + 1], &st->data[loc],
265
0
            sizeof(st->data[0]) * (st->num - loc));
266
0
        st->data[loc] = data;
267
0
    }
268
2.24k
    st->num++;
269
2.24k
    if (st->sorted && st->num > 1) {
270
522
        if (st->comp != NULL) {
271
6
            if (loc > 0 && (st->comp(&st->data[loc - 1], &st->data[loc]) > 0))
272
0
                st->sorted = 0;
273
6
            if (loc < st->num - 1
274
0
                && (st->comp(&st->data[loc + 1], &st->data[loc]) < 0))
275
0
                st->sorted = 0;
276
516
        } else {
277
516
            st->sorted = 0;
278
516
        }
279
522
    }
280
2.24k
    return st->num;
281
2.24k
}
282
283
static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc)
284
3
{
285
3
    const void *ret = st->data[loc];
286
287
3
    if (loc != st->num - 1)
288
0
        memmove(&st->data[loc], &st->data[loc + 1],
289
0
            sizeof(st->data[0]) * (st->num - loc - 1));
290
3
    st->num--;
291
3
    st->sorted = st->sorted || st->num <= 1;
292
293
3
    return (void *)ret;
294
3
}
295
296
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
297
0
{
298
0
    int i;
299
300
0
    if (st == NULL)
301
0
        return NULL;
302
303
0
    for (i = 0; i < st->num; i++)
304
0
        if (st->data[i] == p)
305
0
            return internal_delete(st, i);
306
0
    return NULL;
307
0
}
308
309
void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
310
3
{
311
3
    if (st == NULL || loc < 0 || loc >= st->num)
312
0
        return NULL;
313
314
3
    return internal_delete(st, loc);
315
3
}
316
317
static int internal_find(const OPENSSL_STACK *st, const void *data,
318
    int ret_val_options, int *pnum_matched)
319
24
{
320
24
    const void *r;
321
24
    int i, count = 0;
322
24
    int *pnum = pnum_matched;
323
324
24
    if (st == NULL || st->num == 0)
325
12
        return -1;
326
327
12
    if (pnum == NULL)
328
12
        pnum = &count;
329
330
12
    if (st->comp == NULL) {
331
0
        for (i = 0; i < st->num; i++)
332
0
            if (st->data[i] == data) {
333
0
                *pnum = 1;
334
0
                return i;
335
0
            }
336
0
        *pnum = 0;
337
0
        return -1;
338
0
    }
339
340
12
    if (data == NULL)
341
0
        return -1;
342
343
12
    if (!st->sorted) {
344
0
        int res = -1;
345
346
0
        for (i = 0; i < st->num; i++)
347
0
            if (st->comp(&data, st->data + i) == 0) {
348
0
                if (res == -1)
349
0
                    res = i;
350
0
                ++*pnum;
351
                /* Check if only one result is wanted and exit if so */
352
0
                if (pnum_matched == NULL)
353
0
                    return i;
354
0
            }
355
0
        if (res == -1)
356
0
            *pnum = 0;
357
0
        return res;
358
0
    }
359
360
12
    if (pnum_matched != NULL)
361
0
        ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
362
12
    r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
363
12
        ret_val_options);
364
365
12
    if (pnum_matched != NULL) {
366
0
        *pnum = 0;
367
0
        if (r != NULL) {
368
0
            const void **p = (const void **)r;
369
370
0
            while (p < st->data + st->num) {
371
0
                if (st->comp(&data, p) != 0)
372
0
                    break;
373
0
                ++*pnum;
374
0
                ++p;
375
0
            }
376
0
        }
377
0
    }
378
379
12
    return r == NULL ? -1 : (int)((const void **)r - st->data);
380
12
}
381
382
int OPENSSL_sk_find(const OPENSSL_STACK *st, const void *data)
383
24
{
384
24
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
385
24
}
386
387
int OPENSSL_sk_find_ex(const OPENSSL_STACK *st, const void *data)
388
0
{
389
0
    return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
390
0
}
391
392
int OPENSSL_sk_find_all(const OPENSSL_STACK *st, const void *data, int *pnum)
393
0
{
394
0
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
395
0
}
396
397
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
398
2.24k
{
399
2.24k
    if (st == NULL)
400
0
        return 0;
401
2.24k
    return OPENSSL_sk_insert(st, data, st->num);
402
2.24k
}
403
404
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
405
0
{
406
0
    return OPENSSL_sk_insert(st, data, 0);
407
0
}
408
409
void *OPENSSL_sk_shift(OPENSSL_STACK *st)
410
0
{
411
0
    if (st == NULL || st->num == 0)
412
0
        return NULL;
413
0
    return internal_delete(st, 0);
414
0
}
415
416
void *OPENSSL_sk_pop(OPENSSL_STACK *st)
417
0
{
418
0
    if (st == NULL || st->num == 0)
419
0
        return NULL;
420
0
    return internal_delete(st, st->num - 1);
421
0
}
422
423
void OPENSSL_sk_zero(OPENSSL_STACK *st)
424
0
{
425
0
    if (st == NULL || st->num == 0)
426
0
        return;
427
0
    memset(st->data, 0, sizeof(*st->data) * st->num);
428
0
    st->num = 0;
429
0
}
430
431
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
432
450
{
433
450
    int i;
434
435
450
    if (st == NULL)
436
66
        return;
437
438
835
    for (i = 0; i < st->num; i++) {
439
451
        if (st->data[i] != NULL) {
440
451
            if (st->free_thunk != NULL)
441
160
                st->free_thunk(func, (void *)st->data[i]);
442
291
            else
443
291
                func((void *)st->data[i]);
444
451
        }
445
451
    }
446
384
    OPENSSL_sk_free(st);
447
384
}
448
449
void OPENSSL_sk_free(OPENSSL_STACK *st)
450
1.65k
{
451
1.65k
    if (st == NULL)
452
15
        return;
453
1.64k
    OPENSSL_free(st->data);
454
1.64k
    OPENSSL_free(st);
455
1.64k
}
456
457
int OPENSSL_sk_num(const OPENSSL_STACK *st)
458
3.45k
{
459
3.45k
    return st == NULL ? -1 : st->num;
460
3.45k
}
461
462
void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
463
7.63k
{
464
7.63k
    if (st == NULL || i < 0 || i >= st->num)
465
0
        return NULL;
466
7.63k
    return (void *)st->data[i];
467
7.63k
}
468
469
void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
470
0
{
471
0
    if (st == NULL) {
472
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
473
0
        return NULL;
474
0
    }
475
0
    if (i < 0 || i >= st->num) {
476
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
477
0
            "i=%d", i);
478
0
        return NULL;
479
0
    }
480
0
    st->data[i] = data;
481
0
    st->sorted = st->num <= 1;
482
0
    return (void *)st->data[i];
483
0
}
484
485
void OPENSSL_sk_sort(OPENSSL_STACK *st)
486
216
{
487
216
    if (st != NULL && !st->sorted && st->comp != NULL) {
488
0
        if (st->num > 1)
489
0
            qsort(st->data, st->num, sizeof(void *), st->comp);
490
0
        st->sorted = 1; /* empty or single-element stack is considered sorted */
491
0
    }
492
216
}
493
494
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
495
12
{
496
12
    return st == NULL ? 1 : st->sorted;
497
12
}