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