Coverage Report

Created: 2026-10-28 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/stack/stack.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2026 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
    int (*cmp_thunk)(OPENSSL_sk_compfunc, const void *, const void *);
35
    OPENSSL_sk_freefunc_thunk free_thunk;
36
    OPENSSL_sk_copyfunc_thunk copy_thunk;
37
};
38
39
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk,
40
    OPENSSL_sk_compfunc c)
41
152k
{
42
152k
    OPENSSL_sk_compfunc old = sk->comp;
43
44
152k
    if (sk->comp != c && sk->num > 1)
45
142k
        sk->sorted = 0;
46
152k
    sk->comp = c;
47
48
152k
    return old;
49
152k
}
50
51
static void free_with_thunk(OPENSSL_STACK *sk, OPENSSL_sk_freefunc free_func, const void *data)
52
67.3M
{
53
67.3M
    if (data == NULL)
54
69.8k
        return;
55
67.2M
    if (sk->free_thunk != NULL)
56
67.2M
        sk->free_thunk(free_func, (void *)data);
57
0
    else
58
0
        free_func((void *)data);
59
67.2M
}
60
61
static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
62
    OPENSSL_sk_copyfunc copy_func,
63
    OPENSSL_sk_freefunc free_func)
64
5.86M
{
65
5.86M
    OPENSSL_STACK *ret;
66
5.86M
    int i;
67
68
5.86M
    if ((ret = OPENSSL_sk_new_null()) == NULL)
69
0
        goto err;
70
71
5.86M
    if (sk == NULL)
72
98
        goto done;
73
74
    /* direct structure assignment */
75
5.86M
    *ret = *sk;
76
5.86M
    ret->data = NULL;
77
5.86M
    ret->num_alloc = 0;
78
79
5.86M
    if (ret->num == 0)
80
7
        goto done; /* nothing to copy */
81
82
5.86M
    ret->num_alloc = ret->num > min_nodes ? ret->num : min_nodes;
83
5.86M
    ret->data = OPENSSL_calloc(ret->num_alloc, sizeof(*ret->data));
84
5.86M
    if (ret->data == NULL)
85
0
        goto err;
86
5.86M
    if (copy_func == NULL) {
87
4.93M
        memcpy(ret->data, sk->data, sizeof(*ret->data) * ret->num);
88
4.93M
    } else {
89
10.4M
        for (i = 0; i < ret->num; ++i) {
90
9.47M
            if (sk->data[i] == NULL)
91
0
                continue;
92
9.47M
            if (ret->copy_thunk != NULL)
93
9.47M
                ret->data[i] = ret->copy_thunk(copy_func, sk->data[i]);
94
0
            else
95
0
                ret->data[i] = copy_func(sk->data[i]);
96
97
9.47M
            if (ret->data[i] == NULL) {
98
0
                while (--i >= 0)
99
0
                    free_with_thunk(ret, free_func, ret->data[i]);
100
0
                goto err;
101
0
            }
102
9.47M
        }
103
931k
    }
104
105
5.86M
done:
106
5.86M
    return ret;
107
108
0
err:
109
0
    OPENSSL_sk_free(ret);
110
0
    return NULL;
111
5.86M
}
112
113
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
114
    OPENSSL_sk_copyfunc copy_func,
115
    OPENSSL_sk_freefunc free_func)
116
1.23M
{
117
1.23M
    return internal_copy(sk, copy_func, free_func);
118
1.23M
}
119
120
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
121
6.94M
{
122
6.94M
    return internal_copy(sk, NULL, NULL);
123
6.94M
}
124
125
OPENSSL_STACK *OPENSSL_sk_new_null(void)
126
193M
{
127
193M
    return OPENSSL_sk_new_reserve(NULL, 0);
128
193M
}
129
130
OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
131
29.0M
{
132
29.0M
    return OPENSSL_sk_new_reserve(c, 0);
133
29.0M
}
134
135
/*
136
 * Calculate the array growth based on the target size.
137
 *
138
 * The growth factor is a rational number and is defined by a numerator
139
 * and a denominator.  According to Andrew Koenig in his paper "Why Are
140
 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
141
 * than the golden ratio (1.618...).
142
 *
143
 * Considering only the Fibonacci ratios less than the golden ratio, the
144
 * number of steps from the minimum allocation to integer overflow is:
145
 *      factor  decimal    growths
146
 *       3/2     1.5          51
147
 *       8/5     1.6          45
148
 *      21/13    1.615...     44
149
 *
150
 * All larger factors have the same number of growths.
151
 *
152
 * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice.
153
 */
154
static ossl_inline int compute_growth(int target, int current)
155
6.01M
{
156
6.01M
    int err = 0;
157
158
12.0M
    while (current < target) {
159
6.01M
        if (current >= max_nodes)
160
0
            return 0;
161
162
6.01M
        current = safe_muldiv_int(current, 8, 5, &err);
163
6.01M
        if (err != 0)
164
0
            return 0;
165
6.01M
        if (current >= max_nodes)
166
0
            current = max_nodes;
167
6.01M
    }
168
6.01M
    return current;
169
6.01M
}
170
171
/* internal STACK storage allocation */
172
static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
173
383M
{
174
383M
    const void **tmpdata;
175
383M
    int num_alloc;
176
177
    /* Check to see the reservation isn't exceeding the hard limit */
178
383M
    if (n > max_nodes - st->num) {
179
0
        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
180
0
        return 0;
181
0
    }
182
183
    /* Figure out the new size */
184
383M
    num_alloc = st->num + n;
185
383M
    if (num_alloc < min_nodes)
186
34.6M
        num_alloc = min_nodes;
187
188
    /* If |st->data| allocation was postponed */
189
383M
    if (st->data == NULL) {
190
        /*
191
         * At this point, |st->num_alloc| and |st->num| are 0;
192
         * so |num_alloc| value is |n| or |min_nodes| if greater than |n|.
193
         */
194
26.0M
        if ((st->data = OPENSSL_calloc(num_alloc, sizeof(void *))) == NULL)
195
0
            return 0;
196
26.0M
        st->num_alloc = num_alloc;
197
26.0M
        return 1;
198
26.0M
    }
199
200
356M
    if (!exact) {
201
356M
        if (num_alloc <= st->num_alloc)
202
350M
            return 1;
203
6.01M
        num_alloc = compute_growth(num_alloc, st->num_alloc);
204
6.01M
        if (num_alloc == 0) {
205
0
            ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
206
0
            return 0;
207
0
        }
208
6.01M
    } else if (num_alloc == st->num_alloc) {
209
3.68k
        return 1;
210
3.68k
    }
211
212
6.04M
    tmpdata = OPENSSL_realloc_array((void *)st->data, num_alloc, sizeof(void *));
213
6.04M
    if (tmpdata == NULL)
214
0
        return 0;
215
216
6.04M
    st->data = tmpdata;
217
6.04M
    st->num_alloc = num_alloc;
218
6.04M
    return 1;
219
6.04M
}
220
221
static ossl_inline int cmp_with_thunk(const OPENSSL_STACK *st, const void *a, const void *b)
222
1.29M
{
223
1.29M
    return (st->cmp_thunk == NULL) ? st->comp(a, b) : st->cmp_thunk(st->comp, a, b);
224
1.29M
}
225
226
OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
227
223M
{
228
223M
    OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
229
230
223M
    if (st == NULL)
231
0
        return NULL;
232
233
223M
    st->comp = c;
234
223M
    st->sorted = 1; /* empty or single-element stack is considered sorted */
235
236
223M
    if (n <= 0)
237
222M
        return st;
238
239
558k
    if (!sk_reserve(st, n, 1)) {
240
0
        OPENSSL_sk_free(st);
241
0
        return NULL;
242
0
    }
243
244
558k
    return st;
245
558k
}
246
247
int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
248
37.8k
{
249
37.8k
    if (st == NULL) {
250
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
251
0
        return 0;
252
0
    }
253
254
37.8k
    if (n < 0)
255
0
        return 1;
256
37.8k
    return sk_reserve(st, n, 1);
257
37.8k
}
258
259
OPENSSL_STACK *OPENSSL_sk_set_thunks(OPENSSL_STACK *st, OPENSSL_sk_freefunc_thunk f_thunk)
260
116M
{
261
116M
    if (st != NULL)
262
112M
        st->free_thunk = f_thunk;
263
264
116M
    return st;
265
116M
}
266
267
OPENSSL_STACK *OPENSSL_sk_set_cmp_thunks(OPENSSL_STACK *st, int (*c_thunk)(int (*)(const void *, const void *), const void *, const void *))
268
67.7M
{
269
67.7M
    if (st != NULL)
270
67.7M
        st->cmp_thunk = c_thunk;
271
272
67.7M
    return st;
273
67.7M
}
274
275
OPENSSL_STACK *OPENSSL_sk_set_copy_thunks(OPENSSL_STACK *st, OPENSSL_sk_copyfunc_thunk cp_thunk)
276
64.0M
{
277
64.0M
    if (st != NULL)
278
64.0M
        st->copy_thunk = cp_thunk;
279
280
64.0M
    return st;
281
64.0M
}
282
283
int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
284
155M
{
285
155M
    int cmp_ret;
286
287
155M
    if (st == NULL) {
288
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
289
0
        return 0;
290
0
    }
291
155M
    if (st->num == max_nodes) {
292
0
        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
293
0
        return 0;
294
0
    }
295
296
155M
    if (!sk_reserve(st, 1, 0))
297
0
        return 0;
298
299
155M
    if ((loc >= st->num) || (loc < 0)) {
300
155M
        loc = st->num;
301
155M
        st->data[loc] = data;
302
155M
    } else {
303
3.17k
        memmove(&st->data[loc + 1], &st->data[loc],
304
3.17k
            sizeof(st->data[0]) * (st->num - loc));
305
3.17k
        st->data[loc] = data;
306
3.17k
    }
307
155M
    st->num++;
308
155M
    if (st->sorted && st->num > 1) {
309
3.77M
        if (st->comp != NULL) {
310
1.29M
            if (loc > 0) {
311
1.29M
                cmp_ret = cmp_with_thunk(st, &st->data[loc - 1], &st->data[loc]);
312
1.29M
                if (cmp_ret > 0)
313
8.73k
                    st->sorted = 0;
314
1.29M
            }
315
1.29M
            if (loc < st->num - 1) {
316
0
                cmp_ret = cmp_with_thunk(st, &st->data[loc + 1], &st->data[loc]);
317
0
                if (cmp_ret < 0)
318
0
                    st->sorted = 0;
319
0
            }
320
2.47M
        } else {
321
2.47M
            st->sorted = 0;
322
2.47M
        }
323
3.77M
    }
324
155M
    return st->num;
325
155M
}
326
327
static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc)
328
394k
{
329
394k
    const void *ret = st->data[loc];
330
331
394k
    if (loc != st->num - 1)
332
88.5k
        memmove(&st->data[loc], &st->data[loc + 1],
333
88.5k
            sizeof(st->data[0]) * (st->num - loc - 1));
334
394k
    st->num--;
335
394k
    st->sorted = st->sorted || st->num <= 1;
336
337
394k
    return (void *)ret;
338
394k
}
339
340
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
341
169k
{
342
169k
    int i;
343
344
169k
    if (st == NULL)
345
0
        return NULL;
346
347
831k
    for (i = 0; i < st->num; i++)
348
831k
        if (st->data[i] == p)
349
169k
            return internal_delete(st, i);
350
0
    return NULL;
351
169k
}
352
353
void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
354
206k
{
355
206k
    if (st == NULL || loc < 0 || loc >= st->num)
356
0
        return NULL;
357
358
206k
    return internal_delete(st, loc);
359
206k
}
360
361
static int internal_find(const OPENSSL_STACK *st, const void *data,
362
    int ret_val_options, int *pnum_matched)
363
337k
{
364
337k
    const void *r;
365
337k
    int i, count = 0;
366
337k
    int cmp_ret;
367
337k
    int *pnum = pnum_matched;
368
369
337k
    if (st == NULL || st->num == 0)
370
85.0k
        return -1;
371
372
252k
    if (pnum == NULL)
373
246k
        pnum = &count;
374
375
252k
    if (st->comp == NULL) {
376
3.24M
        for (i = 0; i < st->num; i++)
377
3.23M
            if (st->data[i] == data) {
378
32.4k
                *pnum = 1;
379
32.4k
                return i;
380
32.4k
            }
381
2.43k
        *pnum = 0;
382
2.43k
        return -1;
383
34.9k
    }
384
385
217k
    if (data == NULL)
386
0
        return -1;
387
388
217k
    if (!st->sorted) {
389
0
        int res = -1;
390
391
0
        for (i = 0; i < st->num; i++) {
392
0
            cmp_ret = cmp_with_thunk(st, &data, st->data + i);
393
0
            if (cmp_ret == 0) {
394
0
                if (res == -1)
395
0
                    res = i;
396
0
                ++*pnum;
397
                /* Check if only one result is wanted and exit if so */
398
0
                if (pnum_matched == NULL)
399
0
                    return i;
400
0
            }
401
0
        }
402
0
        if (res == -1)
403
0
            *pnum = 0;
404
0
        return res;
405
0
    }
406
407
217k
    if (pnum_matched != NULL)
408
5.42k
        ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
409
217k
    r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, st->cmp_thunk,
410
217k
        ret_val_options);
411
412
217k
    if (pnum_matched != NULL) {
413
5.42k
        *pnum = 0;
414
5.42k
        if (r != NULL) {
415
4.15k
            const void **p = (const void **)r;
416
417
8.30k
            while (p < st->data + st->num) {
418
4.15k
                cmp_ret = cmp_with_thunk(st, &data, p);
419
4.15k
                if (cmp_ret != 0)
420
0
                    break;
421
4.15k
                ++*pnum;
422
4.15k
                ++p;
423
4.15k
            }
424
4.15k
        }
425
5.42k
    }
426
427
217k
    return r == NULL ? -1 : (int)((const void **)r - st->data);
428
217k
}
429
430
int OPENSSL_sk_find(const OPENSSL_STACK *st, const void *data)
431
268k
{
432
268k
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
433
268k
}
434
435
int OPENSSL_sk_find_ex(const OPENSSL_STACK *st, const void *data)
436
0
{
437
0
    return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
438
0
}
439
440
int OPENSSL_sk_find_all(const OPENSSL_STACK *st, const void *data, int *pnum)
441
68.8k
{
442
68.8k
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
443
68.8k
}
444
445
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
446
382M
{
447
382M
    if (st == NULL)
448
0
        return 0;
449
382M
    return OPENSSL_sk_insert(st, data, st->num);
450
382M
}
451
452
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
453
0
{
454
0
    return OPENSSL_sk_insert(st, data, 0);
455
0
}
456
457
void *OPENSSL_sk_shift(OPENSSL_STACK *st)
458
198
{
459
198
    if (st == NULL || st->num == 0)
460
198
        return NULL;
461
0
    return internal_delete(st, 0);
462
198
}
463
464
void *OPENSSL_sk_pop(OPENSSL_STACK *st)
465
1.57M
{
466
1.57M
    if (st == NULL || st->num == 0)
467
32.1k
        return NULL;
468
1.54M
    return internal_delete(st, st->num - 1);
469
1.57M
}
470
471
void OPENSSL_sk_zero(OPENSSL_STACK *st)
472
0
{
473
0
    if (st == NULL || st->num == 0)
474
0
        return;
475
0
    memset(st->data, 0, sizeof(*st->data) * st->num);
476
0
    st->num = 0;
477
0
}
478
479
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
480
25.5M
{
481
25.5M
    int i;
482
483
25.5M
    if (st == NULL)
484
9.23M
        return;
485
486
83.6M
    for (i = 0; i < st->num; i++)
487
67.3M
        free_with_thunk(st, func, st->data[i]);
488
489
16.2M
    OPENSSL_sk_free(st);
490
16.2M
}
491
492
void OPENSSL_sk_free(OPENSSL_STACK *st)
493
291M
{
494
291M
    if (st == NULL)
495
59.4M
        return;
496
231M
    OPENSSL_free(st->data);
497
231M
    OPENSSL_free(st);
498
231M
}
499
500
int OPENSSL_sk_num(const OPENSSL_STACK *st)
501
1.05G
{
502
1.05G
    return st == NULL ? -1 : st->num;
503
1.05G
}
504
505
void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
506
771M
{
507
771M
    if (st == NULL || i < 0 || i >= st->num)
508
6.10k
        return NULL;
509
771M
    return (void *)st->data[i];
510
771M
}
511
512
void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
513
6.09M
{
514
6.09M
    if (st == NULL) {
515
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
516
0
        return NULL;
517
0
    }
518
6.09M
    if (i < 0 || i >= st->num) {
519
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
520
0
            "i=%d", i);
521
0
        return NULL;
522
0
    }
523
6.09M
    st->data[i] = data;
524
6.09M
    st->sorted = st->num <= 1;
525
6.09M
    return (void *)st->data[i];
526
6.09M
}
527
528
void OPENSSL_sk_sort(OPENSSL_STACK *st)
529
29.1M
{
530
29.1M
    if (st != NULL && !st->sorted && st->comp != NULL) {
531
20.2M
        if (st->num > 1)
532
327k
            qsort(st->data, st->num, sizeof(void *), st->comp);
533
20.2M
        st->sorted = 1; /* empty or single-element stack is considered sorted */
534
20.2M
    }
535
29.1M
}
536
537
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
538
59.4k
{
539
59.4k
    return st == NULL ? 1 : st->sorted;
540
59.4k
}