Coverage Report

Created: 2026-02-22 06:11

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