2 * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include "internal/cryptlib.h"
12 #include "internal/numbers.h"
13 #include "internal/safe_math.h"
14 #include <openssl/stack.h>
16 #include <openssl/e_os2.h> /* For ossl_inline */
18 OSSL_SAFE_MATH_SIGNED(int, int)
21 * The initial number of nodes in the array.
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 *)) : INT_MAX
;
32 OPENSSL_sk_compfunc comp
;
33 OPENSSL_sk_freefunc_thunk free_thunk
;
36 OPENSSL_sk_compfunc
OPENSSL_sk_set_cmp_func(OPENSSL_STACK
*sk
,
37 OPENSSL_sk_compfunc c
)
39 OPENSSL_sk_compfunc old
= sk
->comp
;
48 OPENSSL_STACK
*OPENSSL_sk_dup(const OPENSSL_STACK
*sk
)
52 if ((ret
= OPENSSL_malloc(sizeof(*ret
))) == NULL
)
60 /* direct structure assignment */
64 if (sk
== NULL
|| sk
->num
== 0) {
65 /* postpone |ret->data| allocation */
71 /* duplicate |sk->data| content */
72 ret
->data
= OPENSSL_malloc(sizeof(*ret
->data
) * sk
->num_alloc
);
73 if (ret
->data
== NULL
)
75 memcpy(ret
->data
, sk
->data
, sizeof(void *) * sk
->num
);
83 OPENSSL_STACK
*OPENSSL_sk_deep_copy(const OPENSSL_STACK
*sk
,
84 OPENSSL_sk_copyfunc copy_func
,
85 OPENSSL_sk_freefunc free_func
)
90 if ((ret
= OPENSSL_malloc(sizeof(*ret
))) == NULL
)
98 /* direct structure assignment */
102 if (sk
== NULL
|| sk
->num
== 0) {
103 /* postpone |ret| data allocation */
109 ret
->num_alloc
= sk
->num
> min_nodes
? sk
->num
: min_nodes
;
110 ret
->data
= OPENSSL_zalloc(sizeof(*ret
->data
) * ret
->num_alloc
);
111 if (ret
->data
== NULL
)
114 for (i
= 0; i
< ret
->num
; ++i
) {
115 if (sk
->data
[i
] == NULL
)
117 if ((ret
->data
[i
] = copy_func(sk
->data
[i
])) == NULL
) {
119 if (ret
->data
[i
] != NULL
)
120 free_func((void *)ret
->data
[i
]);
127 OPENSSL_sk_free(ret
);
131 OPENSSL_STACK
*OPENSSL_sk_new_null(void)
133 return OPENSSL_sk_new_reserve(NULL
, 0);
136 OPENSSL_STACK
*OPENSSL_sk_new(OPENSSL_sk_compfunc c
)
138 return OPENSSL_sk_new_reserve(c
, 0);
142 * Calculate the array growth based on the target size.
144 * The growth factor is a rational number and is defined by a numerator
145 * and a denominator. According to Andrew Koenig in his paper "Why Are
146 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
147 * than the golden ratio (1.618...).
149 * Considering only the Fibonacci ratios less than the golden ratio, the
150 * number of steps from the minimum allocation to integer overflow is:
151 * factor decimal growths
156 * All larger factors have the same number of growths.
158 * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice.
160 static ossl_inline
int compute_growth(int target
, int current
)
164 while (current
< target
) {
165 if (current
>= max_nodes
)
168 current
= safe_muldiv_int(current
, 8, 5, &err
);
171 if (current
>= max_nodes
)
177 /* internal STACK storage allocation */
178 static int sk_reserve(OPENSSL_STACK
*st
, int n
, int exact
)
180 const void **tmpdata
;
183 /* Check to see the reservation isn't exceeding the hard limit */
184 if (n
> max_nodes
- st
->num
) {
185 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_TOO_MANY_RECORDS
);
189 /* Figure out the new size */
190 num_alloc
= st
->num
+ n
;
191 if (num_alloc
< min_nodes
)
192 num_alloc
= min_nodes
;
194 /* If |st->data| allocation was postponed */
195 if (st
->data
== NULL
) {
197 * At this point, |st->num_alloc| and |st->num| are 0;
198 * so |num_alloc| value is |n| or |min_nodes| if greater than |n|.
200 if ((st
->data
= OPENSSL_zalloc(sizeof(void *) * num_alloc
)) == NULL
)
202 st
->num_alloc
= num_alloc
;
207 if (num_alloc
<= st
->num_alloc
)
209 num_alloc
= compute_growth(num_alloc
, st
->num_alloc
);
210 if (num_alloc
== 0) {
211 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_TOO_MANY_RECORDS
);
214 } else if (num_alloc
== st
->num_alloc
) {
218 tmpdata
= OPENSSL_realloc((void *)st
->data
, sizeof(void *) * num_alloc
);
223 st
->num_alloc
= num_alloc
;
227 OPENSSL_STACK
*OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c
, int n
)
229 OPENSSL_STACK
*st
= OPENSSL_zalloc(sizeof(OPENSSL_STACK
));
239 if (!sk_reserve(st
, n
, 1)) {
247 int OPENSSL_sk_reserve(OPENSSL_STACK
*st
, int n
)
250 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
256 return sk_reserve(st
, n
, 1);
259 OPENSSL_STACK
*OPENSSL_sk_set_thunks(OPENSSL_STACK
*st
, OPENSSL_sk_freefunc_thunk f_thunk
)
262 st
->free_thunk
= f_thunk
;
267 int OPENSSL_sk_insert(OPENSSL_STACK
*st
, const void *data
, int loc
)
270 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
273 if (st
->num
== max_nodes
) {
274 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_TOO_MANY_RECORDS
);
278 if (!sk_reserve(st
, 1, 0))
281 if ((loc
>= st
->num
) || (loc
< 0)) {
282 st
->data
[st
->num
] = data
;
284 memmove(&st
->data
[loc
+ 1], &st
->data
[loc
],
285 sizeof(st
->data
[0]) * (st
->num
- loc
));
286 st
->data
[loc
] = data
;
293 static ossl_inline
void *internal_delete(OPENSSL_STACK
*st
, int loc
)
295 const void *ret
= st
->data
[loc
];
297 if (loc
!= st
->num
- 1)
298 memmove(&st
->data
[loc
], &st
->data
[loc
+ 1],
299 sizeof(st
->data
[0]) * (st
->num
- loc
- 1));
305 void *OPENSSL_sk_delete_ptr(OPENSSL_STACK
*st
, const void *p
)
312 for (i
= 0; i
< st
->num
; i
++)
313 if (st
->data
[i
] == p
)
314 return internal_delete(st
, i
);
318 void *OPENSSL_sk_delete(OPENSSL_STACK
*st
, int loc
)
320 if (st
== NULL
|| loc
< 0 || loc
>= st
->num
)
323 return internal_delete(st
, loc
);
326 static int internal_find(OPENSSL_STACK
*st
, const void *data
,
327 int ret_val_options
, int *pnum_matched
)
331 int *pnum
= pnum_matched
;
333 if (st
== NULL
|| st
->num
== 0)
339 if (st
->comp
== NULL
) {
340 for (i
= 0; i
< st
->num
; i
++)
341 if (st
->data
[i
] == data
) {
355 for (i
= 0; i
< st
->num
; i
++)
356 if (st
->comp(&data
, st
->data
+ i
) == 0) {
360 /* Check if only one result is wanted and exit if so */
361 if (pnum_matched
== NULL
)
369 if (pnum_matched
!= NULL
)
370 ret_val_options
|= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH
;
371 r
= ossl_bsearch(&data
, st
->data
, st
->num
, sizeof(void *), st
->comp
,
374 if (pnum_matched
!= NULL
) {
377 const void **p
= (const void **)r
;
379 while (p
< st
->data
+ st
->num
) {
380 if (st
->comp(&data
, p
) != 0)
388 return r
== NULL
? -1 : (int)((const void **)r
- st
->data
);
391 int OPENSSL_sk_find(OPENSSL_STACK
*st
, const void *data
)
393 return internal_find(st
, data
, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH
, NULL
);
396 int OPENSSL_sk_find_ex(OPENSSL_STACK
*st
, const void *data
)
398 return internal_find(st
, data
, OSSL_BSEARCH_VALUE_ON_NOMATCH
, NULL
);
401 int OPENSSL_sk_find_all(OPENSSL_STACK
*st
, const void *data
, int *pnum
)
403 return internal_find(st
, data
, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH
, pnum
);
406 int OPENSSL_sk_push(OPENSSL_STACK
*st
, const void *data
)
410 return OPENSSL_sk_insert(st
, data
, st
->num
);
413 int OPENSSL_sk_unshift(OPENSSL_STACK
*st
, const void *data
)
415 return OPENSSL_sk_insert(st
, data
, 0);
418 void *OPENSSL_sk_shift(OPENSSL_STACK
*st
)
420 if (st
== NULL
|| st
->num
== 0)
422 return internal_delete(st
, 0);
425 void *OPENSSL_sk_pop(OPENSSL_STACK
*st
)
427 if (st
== NULL
|| st
->num
== 0)
429 return internal_delete(st
, st
->num
- 1);
432 void OPENSSL_sk_zero(OPENSSL_STACK
*st
)
434 if (st
== NULL
|| st
->num
== 0)
436 memset(st
->data
, 0, sizeof(*st
->data
) * st
->num
);
440 void OPENSSL_sk_pop_free(OPENSSL_STACK
*st
, OPENSSL_sk_freefunc func
)
447 for (i
= 0; i
< st
->num
; i
++) {
448 if (st
->data
[i
] != NULL
) {
449 if (st
->free_thunk
!= NULL
)
450 st
->free_thunk(func
, (void *)st
->data
[i
]);
452 func((void *)st
->data
[i
]);
458 void OPENSSL_sk_free(OPENSSL_STACK
*st
)
462 OPENSSL_free(st
->data
);
466 int OPENSSL_sk_num(const OPENSSL_STACK
*st
)
468 return st
== NULL
? -1 : st
->num
;
471 void *OPENSSL_sk_value(const OPENSSL_STACK
*st
, int i
)
473 if (st
== NULL
|| i
< 0 || i
>= st
->num
)
475 return (void *)st
->data
[i
];
478 void *OPENSSL_sk_set(OPENSSL_STACK
*st
, int i
, const void *data
)
481 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
484 if (i
< 0 || i
>= st
->num
) {
485 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_PASSED_INVALID_ARGUMENT
,
491 return (void *)st
->data
[i
];
494 void OPENSSL_sk_sort(OPENSSL_STACK
*st
)
496 if (st
!= NULL
&& !st
->sorted
&& st
->comp
!= NULL
) {
498 qsort(st
->data
, st
->num
, sizeof(void *), st
->comp
);
499 st
->sorted
= 1; /* empty or single-element stack is considered sorted */
503 int OPENSSL_sk_is_sorted(const OPENSSL_STACK
*st
)
505 return st
== NULL
? 1 : st
->sorted
;