Coverage Report

Created: 2026-05-30 06:06

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-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
0
{
42
0
    OPENSSL_sk_compfunc old = sk->comp;
43
44
0
    if (sk->comp != c && sk->num > 1)
45
0
        sk->sorted = 0;
46
0
    sk->comp = c;
47
48
0
    return old;
49
0
}
50
51
static void free_with_thunk(OPENSSL_STACK *sk, OPENSSL_sk_freefunc free_func, const void *data)
52
2
{
53
2
    if (data == NULL)
54
0
        return;
55
2
    if (sk->free_thunk != NULL)
56
2
        sk->free_thunk(free_func, (void *)data);
57
0
    else
58
0
        free_func((void *)data);
59
2
}
60
61
static OPENSSL_STACK *internal_copy(const OPENSSL_STACK *sk,
62
    OPENSSL_sk_copyfunc copy_func,
63
    OPENSSL_sk_freefunc free_func)
64
552
{
65
552
    OPENSSL_STACK *ret;
66
552
    int i;
67
68
552
    if ((ret = OPENSSL_sk_new_null()) == NULL)
69
0
        goto err;
70
71
552
    if (sk == NULL)
72
4
        goto done;
73
74
    /* direct structure assignment */
75
548
    *ret = *sk;
76
548
    ret->data = NULL;
77
548
    ret->num_alloc = 0;
78
79
548
    if (ret->num == 0)
80
0
        goto done; /* nothing to copy */
81
82
548
    ret->num_alloc = ret->num > min_nodes ? ret->num : min_nodes;
83
548
    ret->data = OPENSSL_calloc(ret->num_alloc, sizeof(*ret->data));
84
548
    if (ret->data == NULL)
85
0
        goto err;
86
548
    if (copy_func == NULL) {
87
548
        memcpy(ret->data, sk->data, sizeof(*ret->data) * ret->num);
88
548
    } else {
89
0
        for (i = 0; i < ret->num; ++i) {
90
0
            if (sk->data[i] == NULL)
91
0
                continue;
92
0
            if (ret->copy_thunk != NULL)
93
0
                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
0
            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
0
        }
103
0
    }
104
105
552
done:
106
552
    return ret;
107
108
0
err:
109
0
    OPENSSL_sk_free(ret);
110
0
    return NULL;
111
548
}
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
4
{
117
4
    return internal_copy(sk, copy_func, free_func);
118
4
}
119
120
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
121
548
{
122
548
    return internal_copy(sk, NULL, NULL);
123
548
}
124
125
OPENSSL_STACK *OPENSSL_sk_new_null(void)
126
727
{
127
727
    return OPENSSL_sk_new_reserve(NULL, 0);
128
727
}
129
130
OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
131
210
{
132
210
    return OPENSSL_sk_new_reserve(c, 0);
133
210
}
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
15
{
156
15
    int err = 0;
157
158
30
    while (current < target) {
159
15
        if (current >= max_nodes)
160
0
            return 0;
161
162
15
        current = safe_muldiv_int(current, 8, 5, &err);
163
15
        if (err != 0)
164
0
            return 0;
165
15
        if (current >= max_nodes)
166
0
            current = max_nodes;
167
15
    }
168
15
    return current;
169
15
}
170
171
/* internal STACK storage allocation */
172
static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
173
496
{
174
496
    const void **tmpdata;
175
496
    int num_alloc;
176
177
    /* Check to see the reservation isn't exceeding the hard limit */
178
496
    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
496
    num_alloc = st->num + n;
185
496
    if (num_alloc < min_nodes)
186
340
        num_alloc = min_nodes;
187
188
    /* If |st->data| allocation was postponed */
189
496
    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
175
        if ((st->data = OPENSSL_calloc(num_alloc, sizeof(void *))) == NULL)
195
0
            return 0;
196
175
        st->num_alloc = num_alloc;
197
175
        return 1;
198
175
    }
199
200
321
    if (!exact) {
201
321
        if (num_alloc <= st->num_alloc)
202
306
            return 1;
203
15
        num_alloc = compute_growth(num_alloc, st->num_alloc);
204
15
        if (num_alloc == 0) {
205
0
            ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS);
206
0
            return 0;
207
0
        }
208
15
    } else if (num_alloc == st->num_alloc) {
209
0
        return 1;
210
0
    }
211
212
15
    tmpdata = OPENSSL_realloc_array((void *)st->data, num_alloc, sizeof(void *));
213
15
    if (tmpdata == NULL)
214
0
        return 0;
215
216
15
    st->data = tmpdata;
217
15
    st->num_alloc = num_alloc;
218
15
    return 1;
219
15
}
220
221
static ossl_inline int cmp_with_thunk(const OPENSSL_STACK *st, const void *a, const void *b)
222
2
{
223
2
    return (st->cmp_thunk == NULL) ? st->comp(a, b) : st->cmp_thunk(st->comp, a, b);
224
2
}
225
226
OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
227
937
{
228
937
    OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
229
230
937
    if (st == NULL)
231
0
        return NULL;
232
233
937
    st->comp = c;
234
937
    st->sorted = 1; /* empty or single-element stack is considered sorted */
235
236
937
    if (n <= 0)
237
937
        return st;
238
239
0
    if (!sk_reserve(st, n, 1)) {
240
0
        OPENSSL_sk_free(st);
241
0
        return NULL;
242
0
    }
243
244
0
    return st;
245
0
}
246
247
int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
248
0
{
249
0
    if (st == NULL) {
250
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
251
0
        return 0;
252
0
    }
253
254
0
    if (n < 0)
255
0
        return 1;
256
0
    return sk_reserve(st, n, 1);
257
0
}
258
259
OPENSSL_STACK *OPENSSL_sk_set_thunks(OPENSSL_STACK *st, OPENSSL_sk_freefunc_thunk f_thunk)
260
586
{
261
586
    if (st != NULL)
262
586
        st->free_thunk = f_thunk;
263
264
586
    return st;
265
586
}
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
250
{
269
250
    if (st != NULL)
270
250
        st->cmp_thunk = c_thunk;
271
272
250
    return st;
273
250
}
274
275
OPENSSL_STACK *OPENSSL_sk_set_copy_thunks(OPENSSL_STACK *st, OPENSSL_sk_copyfunc_thunk cp_thunk)
276
385
{
277
385
    if (st != NULL)
278
385
        st->copy_thunk = cp_thunk;
279
280
385
    return st;
281
385
}
282
283
int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
284
496
{
285
496
    int cmp_ret;
286
287
496
    if (st == NULL) {
288
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
289
0
        return 0;
290
0
    }
291
496
    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
496
    if (!sk_reserve(st, 1, 0))
297
0
        return 0;
298
299
496
    if ((loc >= st->num) || (loc < 0)) {
300
496
        loc = st->num;
301
496
        st->data[loc] = data;
302
496
    } else {
303
0
        memmove(&st->data[loc + 1], &st->data[loc],
304
0
            sizeof(st->data[0]) * (st->num - loc));
305
0
        st->data[loc] = data;
306
0
    }
307
496
    st->num++;
308
496
    if (st->sorted && st->num > 1) {
309
131
        if (st->comp != NULL) {
310
2
            if (loc > 0) {
311
2
                cmp_ret = cmp_with_thunk(st, &st->data[loc - 1], &st->data[loc]);
312
2
                if (cmp_ret > 0)
313
0
                    st->sorted = 0;
314
2
            }
315
2
            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
129
        } else {
321
129
            st->sorted = 0;
322
129
        }
323
131
    }
324
496
    return st->num;
325
496
}
326
327
static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc)
328
0
{
329
0
    const void *ret = st->data[loc];
330
331
0
    if (loc != st->num - 1)
332
0
        memmove(&st->data[loc], &st->data[loc + 1],
333
0
            sizeof(st->data[0]) * (st->num - loc - 1));
334
0
    st->num--;
335
0
    st->sorted = st->sorted || st->num <= 1;
336
337
0
    return (void *)ret;
338
0
}
339
340
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
341
0
{
342
0
    int i;
343
344
0
    if (st == NULL)
345
0
        return NULL;
346
347
0
    for (i = 0; i < st->num; i++)
348
0
        if (st->data[i] == p)
349
0
            return internal_delete(st, i);
350
0
    return NULL;
351
0
}
352
353
void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
354
0
{
355
0
    if (st == NULL || loc < 0 || loc >= st->num)
356
0
        return NULL;
357
358
0
    return internal_delete(st, loc);
359
0
}
360
361
static int internal_find(const OPENSSL_STACK *st, const void *data,
362
    int ret_val_options, int *pnum_matched)
363
8
{
364
8
    const void *r;
365
8
    int i, count = 0;
366
8
    int cmp_ret;
367
8
    int *pnum = pnum_matched;
368
369
8
    if (st == NULL || st->num == 0)
370
4
        return -1;
371
372
4
    if (pnum == NULL)
373
4
        pnum = &count;
374
375
4
    if (st->comp == NULL) {
376
0
        for (i = 0; i < st->num; i++)
377
0
            if (st->data[i] == data) {
378
0
                *pnum = 1;
379
0
                return i;
380
0
            }
381
0
        *pnum = 0;
382
0
        return -1;
383
0
    }
384
385
4
    if (data == NULL)
386
0
        return -1;
387
388
4
    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
4
    if (pnum_matched != NULL)
408
0
        ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
409
4
    r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, st->cmp_thunk,
410
4
        ret_val_options);
411
412
4
    if (pnum_matched != NULL) {
413
0
        *pnum = 0;
414
0
        if (r != NULL) {
415
0
            const void **p = (const void **)r;
416
417
0
            while (p < st->data + st->num) {
418
0
                cmp_ret = cmp_with_thunk(st, &data, p);
419
0
                if (cmp_ret != 0)
420
0
                    break;
421
0
                ++*pnum;
422
0
                ++p;
423
0
            }
424
0
        }
425
0
    }
426
427
4
    return r == NULL ? -1 : (int)((const void **)r - st->data);
428
4
}
429
430
int OPENSSL_sk_find(const OPENSSL_STACK *st, const void *data)
431
8
{
432
8
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
433
8
}
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
0
{
442
0
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
443
0
}
444
445
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
446
496
{
447
496
    if (st == NULL)
448
0
        return 0;
449
496
    return OPENSSL_sk_insert(st, data, st->num);
450
496
}
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
0
{
459
0
    if (st == NULL || st->num == 0)
460
0
        return NULL;
461
0
    return internal_delete(st, 0);
462
0
}
463
464
void *OPENSSL_sk_pop(OPENSSL_STACK *st)
465
0
{
466
0
    if (st == NULL || st->num == 0)
467
0
        return NULL;
468
0
    return internal_delete(st, st->num - 1);
469
0
}
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
204
{
481
204
    int i;
482
483
204
    if (st == NULL)
484
0
        return;
485
486
206
    for (i = 0; i < st->num; i++)
487
2
        free_with_thunk(st, func, st->data[i]);
488
489
204
    OPENSSL_sk_free(st);
490
204
}
491
492
void OPENSSL_sk_free(OPENSSL_STACK *st)
493
752
{
494
752
    if (st == NULL)
495
0
        return;
496
752
    OPENSSL_free(st->data);
497
752
    OPENSSL_free(st);
498
752
}
499
500
int OPENSSL_sk_num(const OPENSSL_STACK *st)
501
1.24k
{
502
1.24k
    return st == NULL ? -1 : st->num;
503
1.24k
}
504
505
void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
506
3.58k
{
507
3.58k
    if (st == NULL || i < 0 || i >= st->num)
508
0
        return NULL;
509
3.58k
    return (void *)st->data[i];
510
3.58k
}
511
512
void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
513
0
{
514
0
    if (st == NULL) {
515
0
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
516
0
        return NULL;
517
0
    }
518
0
    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
0
    st->data[i] = data;
524
0
    st->sorted = st->num <= 1;
525
0
    return (void *)st->data[i];
526
0
}
527
528
void OPENSSL_sk_sort(OPENSSL_STACK *st)
529
204
{
530
204
    if (st != NULL && !st->sorted && st->comp != NULL) {
531
0
        if (st->num > 1)
532
0
            qsort(st->data, st->num, sizeof(void *), st->comp);
533
0
        st->sorted = 1; /* empty or single-element stack is considered sorted */
534
0
    }
535
204
}
536
537
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
538
4
{
539
4
    return st == NULL ? 1 : st->sorted;
540
4
}