]>
Commit | Line | Data |
---|---|---|
4f22f405 | 1 | /* |
b6461792 | 2 | * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
4fc56f90 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
4f22f405 RS |
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 | |
d02b48c6 | 8 | */ |
4f22f405 | 9 | |
d02b48c6 | 10 | #include <stdio.h> |
b39fc560 | 11 | #include "internal/cryptlib.h" |
9205ebeb | 12 | #include "internal/numbers.h" |
8347bfa0 | 13 | #include "internal/safe_math.h" |
ec577822 | 14 | #include <openssl/stack.h> |
1b3e2bbf P |
15 | #include <errno.h> |
16 | #include <openssl/e_os2.h> /* For ossl_inline */ | |
17 | ||
8347bfa0 P |
18 | OSSL_SAFE_MATH_SIGNED(int, int) |
19 | ||
1b3e2bbf P |
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 | |
30eba7f3 | 25 | ? (int)(SIZE_MAX / sizeof(void *)) : INT_MAX; |
d02b48c6 | 26 | |
31c2b6ee DSH |
27 | struct stack_st { |
28 | int num; | |
1b3e2bbf | 29 | const void **data; |
31c2b6ee | 30 | int sorted; |
1b3e2bbf | 31 | int num_alloc; |
739a1eb1 | 32 | OPENSSL_sk_compfunc comp; |
21b170df | 33 | OPENSSL_sk_freefunc_thunk free_thunk; |
31c2b6ee DSH |
34 | }; |
35 | ||
30eba7f3 DDO |
36 | OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, |
37 | OPENSSL_sk_compfunc c) | |
739a1eb1 RS |
38 | { |
39 | OPENSSL_sk_compfunc old = sk->comp; | |
eb90a483 | 40 | |
0f113f3e MC |
41 | if (sk->comp != c) |
42 | sk->sorted = 0; | |
43 | sk->comp = c; | |
eb90a483 | 44 | |
0f113f3e MC |
45 | return old; |
46 | } | |
d02b48c6 | 47 | |
c0c9c0c0 | 48 | OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) |
0f113f3e | 49 | { |
739a1eb1 | 50 | OPENSSL_STACK *ret; |
9205ebeb | 51 | |
d53b437f DDO |
52 | if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) |
53 | goto err; | |
7e1445b0 | 54 | |
d53b437f DDO |
55 | if (sk == NULL) { |
56 | ret->num = 0; | |
57 | ret->sorted = 0; | |
58 | ret->comp = NULL; | |
59 | } else { | |
60 | /* direct structure assignment */ | |
61 | *ret = *sk; | |
62 | } | |
0f113f3e | 63 | |
d53b437f | 64 | if (sk == NULL || sk->num == 0) { |
8e8e507e F |
65 | /* postpone |ret->data| allocation */ |
66 | ret->data = NULL; | |
67 | ret->num_alloc = 0; | |
68 | return ret; | |
69 | } | |
d53b437f | 70 | |
8e8e507e | 71 | /* duplicate |sk->data| content */ |
30eba7f3 DDO |
72 | ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc); |
73 | if (ret->data == NULL) | |
7e1445b0 | 74 | goto err; |
1b3e2bbf | 75 | memcpy(ret->data, sk->data, sizeof(void *) * sk->num); |
7e1445b0 | 76 | return ret; |
d53b437f | 77 | |
0f113f3e | 78 | err: |
739a1eb1 | 79 | OPENSSL_sk_free(ret); |
7e1445b0 | 80 | return NULL; |
0f113f3e MC |
81 | } |
82 | ||
c0c9c0c0 | 83 | OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, |
30eba7f3 DDO |
84 | OPENSSL_sk_copyfunc copy_func, |
85 | OPENSSL_sk_freefunc free_func) | |
0f113f3e | 86 | { |
739a1eb1 | 87 | OPENSSL_STACK *ret; |
0f113f3e MC |
88 | int i; |
89 | ||
d53b437f DDO |
90 | if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) |
91 | goto err; | |
7e1445b0 | 92 | |
d53b437f DDO |
93 | if (sk == NULL) { |
94 | ret->num = 0; | |
95 | ret->sorted = 0; | |
96 | ret->comp = NULL; | |
97 | } else { | |
98 | /* direct structure assignment */ | |
99 | *ret = *sk; | |
100 | } | |
7e1445b0 | 101 | |
d53b437f | 102 | if (sk == NULL || sk->num == 0) { |
8e8e507e F |
103 | /* postpone |ret| data allocation */ |
104 | ret->data = NULL; | |
105 | ret->num_alloc = 0; | |
106 | return ret; | |
107 | } | |
108 | ||
1b3e2bbf | 109 | ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes; |
7e1445b0 | 110 | ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); |
d53b437f DDO |
111 | if (ret->data == NULL) |
112 | goto err; | |
0f113f3e MC |
113 | |
114 | for (i = 0; i < ret->num; ++i) { | |
115 | if (sk->data[i] == NULL) | |
116 | continue; | |
117 | if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { | |
118 | while (--i >= 0) | |
119 | if (ret->data[i] != NULL) | |
36639907 | 120 | free_func((void *)ret->data[i]); |
d53b437f | 121 | goto err; |
0f113f3e MC |
122 | } |
123 | } | |
124 | return ret; | |
d53b437f DDO |
125 | |
126 | err: | |
d53b437f DDO |
127 | OPENSSL_sk_free(ret); |
128 | return NULL; | |
0f113f3e | 129 | } |
66d884f0 | 130 | |
739a1eb1 | 131 | OPENSSL_STACK *OPENSSL_sk_new_null(void) |
0f113f3e | 132 | { |
3ceab379 | 133 | return OPENSSL_sk_new_reserve(NULL, 0); |
0f113f3e MC |
134 | } |
135 | ||
739a1eb1 | 136 | OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c) |
0f113f3e | 137 | { |
3ceab379 | 138 | return OPENSSL_sk_new_reserve(c, 0); |
0f113f3e | 139 | } |
d02b48c6 | 140 | |
1b3e2bbf P |
141 | /* |
142 | * Calculate the array growth based on the target size. | |
143 | * | |
8347bfa0 | 144 | * The growth factor is a rational number and is defined by a numerator |
1b3e2bbf P |
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...). | |
148 | * | |
8347bfa0 P |
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 | |
152 | * 3/2 1.5 51 | |
153 | * 8/5 1.6 45 | |
154 | * 21/13 1.615... 44 | |
1b3e2bbf | 155 | * |
8347bfa0 | 156 | * All larger factors have the same number of growths. |
8e8e507e | 157 | * |
8347bfa0 | 158 | * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice. |
1b3e2bbf P |
159 | */ |
160 | static ossl_inline int compute_growth(int target, int current) | |
0f113f3e | 161 | { |
8347bfa0 | 162 | int err = 0; |
1b3e2bbf P |
163 | |
164 | while (current < target) { | |
1b3e2bbf P |
165 | if (current >= max_nodes) |
166 | return 0; | |
167 | ||
8347bfa0 | 168 | current = safe_muldiv_int(current, 8, 5, &err); |
30eba7f3 | 169 | if (err != 0) |
8347bfa0 | 170 | return 0; |
7cc5738a | 171 | if (current >= max_nodes) |
8347bfa0 | 172 | current = max_nodes; |
9731a9ce | 173 | } |
1b3e2bbf P |
174 | return current; |
175 | } | |
9731a9ce | 176 | |
8e8e507e | 177 | /* internal STACK storage allocation */ |
1b3e2bbf P |
178 | static int sk_reserve(OPENSSL_STACK *st, int n, int exact) |
179 | { | |
180 | const void **tmpdata; | |
181 | int num_alloc; | |
9731a9ce | 182 | |
1b3e2bbf | 183 | /* Check to see the reservation isn't exceeding the hard limit */ |
30eba7f3 DDO |
184 | if (n > max_nodes - st->num) { |
185 | ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); | |
1b3e2bbf | 186 | return 0; |
30eba7f3 | 187 | } |
9731a9ce | 188 | |
1b3e2bbf P |
189 | /* Figure out the new size */ |
190 | num_alloc = st->num + n; | |
191 | if (num_alloc < min_nodes) | |
192 | num_alloc = min_nodes; | |
9731a9ce | 193 | |
8e8e507e F |
194 | /* If |st->data| allocation was postponed */ |
195 | if (st->data == NULL) { | |
196 | /* | |
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|. | |
199 | */ | |
e077455e | 200 | if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) |
8e8e507e F |
201 | return 0; |
202 | st->num_alloc = num_alloc; | |
203 | return 1; | |
204 | } | |
205 | ||
1b3e2bbf P |
206 | if (!exact) { |
207 | if (num_alloc <= st->num_alloc) | |
208 | return 1; | |
209 | num_alloc = compute_growth(num_alloc, st->num_alloc); | |
30eba7f3 DDO |
210 | if (num_alloc == 0) { |
211 | ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); | |
9205ebeb | 212 | return 0; |
30eba7f3 | 213 | } |
1b3e2bbf P |
214 | } else if (num_alloc == st->num_alloc) { |
215 | return 1; | |
0f113f3e | 216 | } |
1b3e2bbf P |
217 | |
218 | tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); | |
e077455e | 219 | if (tmpdata == NULL) |
1b3e2bbf P |
220 | return 0; |
221 | ||
222 | st->data = tmpdata; | |
223 | st->num_alloc = num_alloc; | |
224 | return 1; | |
225 | } | |
226 | ||
3ceab379 PY |
227 | OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) |
228 | { | |
229 | OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); | |
230 | ||
e077455e | 231 | if (st == NULL) |
3ceab379 PY |
232 | return NULL; |
233 | ||
234 | st->comp = c; | |
235 | ||
236 | if (n <= 0) | |
237 | return st; | |
238 | ||
239 | if (!sk_reserve(st, n, 1)) { | |
240 | OPENSSL_sk_free(st); | |
241 | return NULL; | |
242 | } | |
243 | ||
244 | return st; | |
245 | } | |
246 | ||
1b3e2bbf P |
247 | int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) |
248 | { | |
30eba7f3 DDO |
249 | if (st == NULL) { |
250 | ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); | |
1049ae98 | 251 | return 0; |
30eba7f3 | 252 | } |
1049ae98 | 253 | |
1b3e2bbf P |
254 | if (n < 0) |
255 | return 1; | |
256 | return sk_reserve(st, n, 1); | |
257 | } | |
258 | ||
21b170df FWH |
259 | OPENSSL_STACK *OPENSSL_sk_set_thunks(OPENSSL_STACK *st, OPENSSL_sk_freefunc_thunk f_thunk) |
260 | { | |
261 | if (st != NULL) | |
262 | st->free_thunk = f_thunk; | |
263 | ||
264 | return st; | |
265 | } | |
266 | ||
1b3e2bbf P |
267 | int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc) |
268 | { | |
30eba7f3 DDO |
269 | if (st == NULL) { |
270 | ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); | |
1b3e2bbf | 271 | return 0; |
30eba7f3 DDO |
272 | } |
273 | if (st->num == max_nodes) { | |
274 | ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); | |
275 | return 0; | |
276 | } | |
1b3e2bbf P |
277 | |
278 | if (!sk_reserve(st, 1, 0)) | |
279 | return 0; | |
280 | ||
9205ebeb | 281 | if ((loc >= st->num) || (loc < 0)) { |
0f113f3e | 282 | st->data[st->num] = data; |
9205ebeb | 283 | } else { |
36639907 RS |
284 | memmove(&st->data[loc + 1], &st->data[loc], |
285 | sizeof(st->data[0]) * (st->num - loc)); | |
0f113f3e MC |
286 | st->data[loc] = data; |
287 | } | |
288 | st->num++; | |
289 | st->sorted = 0; | |
9205ebeb | 290 | return st->num; |
0f113f3e | 291 | } |
d02b48c6 | 292 | |
8e8e507e F |
293 | static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc) |
294 | { | |
295 | const void *ret = st->data[loc]; | |
296 | ||
297 | if (loc != st->num - 1) | |
30eba7f3 DDO |
298 | memmove(&st->data[loc], &st->data[loc + 1], |
299 | sizeof(st->data[0]) * (st->num - loc - 1)); | |
8e8e507e F |
300 | st->num--; |
301 | ||
302 | return (void *)ret; | |
303 | } | |
304 | ||
4591e5fb | 305 | void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p) |
0f113f3e MC |
306 | { |
307 | int i; | |
d02b48c6 | 308 | |
a8086e6b TM |
309 | if (st == NULL) |
310 | return NULL; | |
311 | ||
0f113f3e MC |
312 | for (i = 0; i < st->num; i++) |
313 | if (st->data[i] == p) | |
8e8e507e | 314 | return internal_delete(st, i); |
4591e5fb | 315 | return NULL; |
0f113f3e | 316 | } |
d02b48c6 | 317 | |
739a1eb1 | 318 | void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) |
0f113f3e | 319 | { |
a8086e6b | 320 | if (st == NULL || loc < 0 || loc >= st->num) |
30eba7f3 | 321 | return NULL; |
0f113f3e | 322 | |
8e8e507e | 323 | return internal_delete(st, loc); |
0f113f3e | 324 | } |
d02b48c6 | 325 | |
4591e5fb | 326 | static int internal_find(OPENSSL_STACK *st, const void *data, |
eb0935fd | 327 | int ret_val_options, int *pnum_matched) |
0f113f3e | 328 | { |
36639907 | 329 | const void *r; |
eb0935fd P |
330 | int i, count = 0; |
331 | int *pnum = pnum_matched; | |
0f113f3e | 332 | |
1049ae98 | 333 | if (st == NULL || st->num == 0) |
0f113f3e MC |
334 | return -1; |
335 | ||
eb0935fd P |
336 | if (pnum == NULL) |
337 | pnum = &count; | |
338 | ||
0f113f3e MC |
339 | if (st->comp == NULL) { |
340 | for (i = 0; i < st->num; i++) | |
5fd7eb5c | 341 | if (st->data[i] == data) { |
eb0935fd | 342 | *pnum = 1; |
fbb7b33b | 343 | return i; |
5fd7eb5c | 344 | } |
eb0935fd | 345 | *pnum = 0; |
fbb7b33b AP |
346 | return -1; |
347 | } | |
348 | ||
0f113f3e | 349 | if (data == NULL) |
fbb7b33b | 350 | return -1; |
eb0935fd P |
351 | |
352 | if (!st->sorted) { | |
353 | int res = -1; | |
354 | ||
355 | for (i = 0; i < st->num; i++) | |
356 | if (st->comp(&data, st->data + i) == 0) { | |
357 | if (res == -1) | |
358 | res = i; | |
359 | ++*pnum; | |
360 | /* Check if only one result is wanted and exit if so */ | |
361 | if (pnum_matched == NULL) | |
362 | return i; | |
363 | } | |
364 | if (res == -1) | |
365 | *pnum = 0; | |
366 | return res; | |
367 | } | |
368 | ||
369 | if (pnum_matched != NULL) | |
5fd7eb5c | 370 | ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH; |
5c3f1e34 RL |
371 | r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, |
372 | ret_val_options); | |
fbb7b33b | 373 | |
eb0935fd | 374 | if (pnum_matched != NULL) { |
5fd7eb5c TM |
375 | *pnum = 0; |
376 | if (r != NULL) { | |
377 | const void **p = (const void **)r; | |
378 | ||
379 | while (p < st->data + st->num) { | |
380 | if (st->comp(&data, p) != 0) | |
381 | break; | |
382 | ++*pnum; | |
383 | ++p; | |
384 | } | |
385 | } | |
386 | } | |
387 | ||
fbb7b33b | 388 | return r == NULL ? -1 : (int)((const void **)r - st->data); |
0f113f3e | 389 | } |
26851b6b | 390 | |
4591e5fb | 391 | int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data) |
0f113f3e | 392 | { |
5fd7eb5c | 393 | return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL); |
0f113f3e MC |
394 | } |
395 | ||
4591e5fb | 396 | int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data) |
0f113f3e | 397 | { |
5fd7eb5c TM |
398 | return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL); |
399 | } | |
400 | ||
401 | int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum) | |
402 | { | |
403 | return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum); | |
0f113f3e | 404 | } |
d02b48c6 | 405 | |
36639907 | 406 | int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data) |
0f113f3e | 407 | { |
1049ae98 | 408 | if (st == NULL) |
98d6016a | 409 | return 0; |
8e8e507e | 410 | return OPENSSL_sk_insert(st, data, st->num); |
0f113f3e | 411 | } |
d02b48c6 | 412 | |
36639907 | 413 | int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data) |
0f113f3e | 414 | { |
fbb7b33b | 415 | return OPENSSL_sk_insert(st, data, 0); |
0f113f3e | 416 | } |
d02b48c6 | 417 | |
739a1eb1 | 418 | void *OPENSSL_sk_shift(OPENSSL_STACK *st) |
0f113f3e | 419 | { |
a8086e6b | 420 | if (st == NULL || st->num == 0) |
30eba7f3 | 421 | return NULL; |
8e8e507e | 422 | return internal_delete(st, 0); |
0f113f3e | 423 | } |
d02b48c6 | 424 | |
739a1eb1 | 425 | void *OPENSSL_sk_pop(OPENSSL_STACK *st) |
0f113f3e | 426 | { |
a8086e6b | 427 | if (st == NULL || st->num == 0) |
8e8e507e F |
428 | return NULL; |
429 | return internal_delete(st, st->num - 1); | |
0f113f3e | 430 | } |
d02b48c6 | 431 | |
739a1eb1 | 432 | void OPENSSL_sk_zero(OPENSSL_STACK *st) |
0f113f3e | 433 | { |
a8086e6b | 434 | if (st == NULL || st->num == 0) |
0f113f3e | 435 | return; |
16f8d4eb | 436 | memset(st->data, 0, sizeof(*st->data) * st->num); |
0f113f3e MC |
437 | st->num = 0; |
438 | } | |
439 | ||
739a1eb1 | 440 | void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func) |
0f113f3e MC |
441 | { |
442 | int i; | |
443 | ||
444 | if (st == NULL) | |
445 | return; | |
21b170df FWH |
446 | |
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]); | |
451 | else | |
452 | func((void *)st->data[i]); | |
453 | } | |
454 | } | |
739a1eb1 | 455 | OPENSSL_sk_free(st); |
0f113f3e | 456 | } |
d02b48c6 | 457 | |
739a1eb1 | 458 | void OPENSSL_sk_free(OPENSSL_STACK *st) |
0f113f3e MC |
459 | { |
460 | if (st == NULL) | |
461 | return; | |
b548a1f1 | 462 | OPENSSL_free(st->data); |
0f113f3e MC |
463 | OPENSSL_free(st); |
464 | } | |
d02b48c6 | 465 | |
739a1eb1 | 466 | int OPENSSL_sk_num(const OPENSSL_STACK *st) |
e84240d4 | 467 | { |
fbb7b33b | 468 | return st == NULL ? -1 : st->num; |
e84240d4 DSH |
469 | } |
470 | ||
739a1eb1 | 471 | void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i) |
e84240d4 | 472 | { |
a8086e6b | 473 | if (st == NULL || i < 0 || i >= st->num) |
0f113f3e | 474 | return NULL; |
36639907 | 475 | return (void *)st->data[i]; |
e84240d4 DSH |
476 | } |
477 | ||
36639907 | 478 | void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data) |
e84240d4 | 479 | { |
30eba7f3 | 480 | if (st == NULL) { |
3a09dfb4 | 481 | ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); |
0f113f3e | 482 | return NULL; |
30eba7f3 DDO |
483 | } |
484 | if (i < 0 || i >= st->num) { | |
3a09dfb4 | 485 | ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT, |
30eba7f3 DDO |
486 | "i=%d", i); |
487 | return NULL; | |
488 | } | |
36639907 | 489 | st->data[i] = data; |
fbb7b33b | 490 | st->sorted = 0; |
36639907 | 491 | return (void *)st->data[i]; |
e84240d4 | 492 | } |
ee8ba0b2 | 493 | |
739a1eb1 | 494 | void OPENSSL_sk_sort(OPENSSL_STACK *st) |
0f113f3e | 495 | { |
1049ae98 | 496 | if (st != NULL && !st->sorted && st->comp != NULL) { |
fbb7b33b | 497 | if (st->num > 1) |
8e8e507e | 498 | qsort(st->data, st->num, sizeof(void *), st->comp); |
fbb7b33b | 499 | st->sorted = 1; /* empty or single-element stack is considered sorted */ |
0f113f3e MC |
500 | } |
501 | } | |
2f605e8d | 502 | |
739a1eb1 | 503 | int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st) |
0f113f3e | 504 | { |
1049ae98 | 505 | return st == NULL ? 1 : st->sorted; |
0f113f3e | 506 | } |