| 
									
										
										
										
											2016-05-18 02:51:04 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:18:40 +08:00
										 |  |  |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-18 02:51:04 +08:00
										 |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-05-18 02:51:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2015-05-14 22:56:48 +08:00
										 |  |  | #include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  | #include "internal/numbers.h"
 | 
					
						
							| 
									
										
										
										
											1999-04-24 06:13:45 +08:00
										 |  |  | #include <openssl/stack.h>
 | 
					
						
							| 
									
										
										
										
											2003-04-30 04:46:32 +08:00
										 |  |  | #include <openssl/objects.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <openssl/e_os2.h>      /* For ossl_inline */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * The initial number of nodes in the array. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static const int min_nodes = 4; | 
					
						
							|  |  |  | static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX | 
					
						
							|  |  |  |                              ? (int)(SIZE_MAX / sizeof(void *)) | 
					
						
							|  |  |  |                              : INT_MAX; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-05 23:17:33 +08:00
										 |  |  | struct stack_st { | 
					
						
							|  |  |  |     int num; | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     const void **data; | 
					
						
							| 
									
										
										
										
											2015-03-05 23:17:33 +08:00
										 |  |  |     int sorted; | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     int num_alloc; | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_sk_compfunc comp; | 
					
						
							| 
									
										
										
										
											2015-03-05 23:17:33 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     OPENSSL_sk_compfunc old = sk->comp; | 
					
						
							| 
									
										
										
										
											1999-03-01 01:41:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (sk->comp != c) | 
					
						
							|  |  |  |         sk->sorted = 0; | 
					
						
							|  |  |  |     sk->comp = c; | 
					
						
							| 
									
										
										
										
											1999-03-01 01:41:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     return old; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 21:05:24 +08:00
										 |  |  | OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_STACK *ret; | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { | 
					
						
							|  |  |  |         CRYPTOerr(CRYPTO_F_OPENSSL_SK_DUP, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* direct structure assignment */ | 
					
						
							|  |  |  |     *ret = *sk; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |     if (sk->num == 0) { | 
					
						
							|  |  |  |         /* postpone |ret->data| allocation */ | 
					
						
							|  |  |  |         ret->data = NULL; | 
					
						
							|  |  |  |         ret->num_alloc = 0; | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* duplicate |sk->data| content */ | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |     if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     memcpy(ret->data, sk->data, sizeof(void *) * sk->num); | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  err: | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_sk_free(ret); | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 21:05:24 +08:00
										 |  |  | OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, | 
					
						
							|  |  |  |                              OPENSSL_sk_copyfunc copy_func, | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |                              OPENSSL_sk_freefunc free_func) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_STACK *ret; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { | 
					
						
							|  |  |  |         CRYPTOerr(CRYPTO_F_OPENSSL_SK_DEEP_COPY, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* direct structure assignment */ | 
					
						
							|  |  |  |     *ret = *sk; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |     if (sk->num == 0) { | 
					
						
							|  |  |  |         /* postpone |ret| data allocation */ | 
					
						
							|  |  |  |         ret->data = NULL; | 
					
						
							|  |  |  |         ret->num_alloc = 0; | 
					
						
							|  |  |  |         return ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes; | 
					
						
							| 
									
										
										
										
											2016-06-02 06:59:34 +08:00
										 |  |  |     ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (ret->data == NULL) { | 
					
						
							|  |  |  |         OPENSSL_free(ret); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < ret->num; ++i) { | 
					
						
							|  |  |  |         if (sk->data[i] == NULL) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { | 
					
						
							|  |  |  |             while (--i >= 0) | 
					
						
							|  |  |  |                 if (ret->data[i] != NULL) | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |                     free_func((void *)ret->data[i]); | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |             OPENSSL_sk_free(ret); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-06-22 16:24:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | OPENSSL_STACK *OPENSSL_sk_new_null(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-20 01:42:39 +08:00
										 |  |  |     return OPENSSL_sk_new_reserve(NULL, 0); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-20 01:42:39 +08:00
										 |  |  |     return OPENSSL_sk_new_reserve(c, 0); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Calculate the array growth based on the target size. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |  * The growth fraction is a rational number and is defined by a numerator | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |  * and a denominator.  According to Andrew Koenig in his paper "Why Are | 
					
						
							|  |  |  |  * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less | 
					
						
							|  |  |  |  * than the golden ratio (1.618...). | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |  * We use 3/2 = 1.5 for simplicity of calculation and overflow checking. | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |  * Another option 8/5 = 1.6 allows for slightly faster growth, although safe | 
					
						
							|  |  |  |  * computation is more difficult. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The limit to avoid overflow is spot on.  The modulo three correction term | 
					
						
							|  |  |  |  * ensures that the limit is the largest number than can be expanded by the | 
					
						
							|  |  |  |  * growth factor without exceeding the hard limit. | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Do not call it with |current| lower than 2, or it will infinitely loop. | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | static ossl_inline int compute_growth(int target, int current) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     const int limit = (max_nodes / 3) * 2 + (max_nodes % 3 ? 1 : 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (current < target) { | 
					
						
							|  |  |  |         /* Check to see if we're at the hard limit */ | 
					
						
							|  |  |  |         if (current >= max_nodes) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Expand the size by a factor of 3/2 if it is within range */ | 
					
						
							|  |  |  |         current = current < limit ? current + current / 2 : max_nodes; | 
					
						
							| 
									
										
										
										
											2016-09-08 17:43:37 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     return current; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-09-08 17:43:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  | /* internal STACK storage allocation */ | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  | static int sk_reserve(OPENSSL_STACK *st, int n, int exact) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const void **tmpdata; | 
					
						
							|  |  |  |     int num_alloc; | 
					
						
							| 
									
										
										
										
											2016-09-08 17:43:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     /* Check to see the reservation isn't exceeding the hard limit */ | 
					
						
							|  |  |  |     if (n > max_nodes - st->num) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2016-09-08 17:43:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     /* Figure out the new size */ | 
					
						
							|  |  |  |     num_alloc = st->num + n; | 
					
						
							|  |  |  |     if (num_alloc < min_nodes) | 
					
						
							|  |  |  |         num_alloc = min_nodes; | 
					
						
							| 
									
										
										
										
											2016-09-08 17:43:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |     /* If |st->data| allocation was postponed */ | 
					
						
							|  |  |  |     if (st->data == NULL) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * At this point, |st->num_alloc| and |st->num| are 0; | 
					
						
							|  |  |  |          * so |num_alloc| value is |n| or |min_nodes| if greater than |n|. | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2018-04-03 23:31:16 +08:00
										 |  |  |         if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) { | 
					
						
							| 
									
										
										
										
											2018-04-27 02:02:24 +08:00
										 |  |  |             CRYPTOerr(CRYPTO_F_SK_RESERVE, ERR_R_MALLOC_FAILURE); | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2018-04-03 23:31:16 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |         st->num_alloc = num_alloc; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     if (!exact) { | 
					
						
							|  |  |  |         if (num_alloc <= st->num_alloc) | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         num_alloc = compute_growth(num_alloc, st->num_alloc); | 
					
						
							|  |  |  |         if (num_alloc == 0) | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     } else if (num_alloc == st->num_alloc) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); | 
					
						
							|  |  |  |     if (tmpdata == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     st->data = tmpdata; | 
					
						
							|  |  |  |     st->num_alloc = num_alloc; | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-20 01:42:39 +08:00
										 |  |  | OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (st == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     st->comp = c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (n <= 0) | 
					
						
							|  |  |  |         return st; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!sk_reserve(st, n, 1)) { | 
					
						
							|  |  |  |         OPENSSL_sk_free(st); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return st; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  | int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |     if (n < 0) | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     return sk_reserve(st, n, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || st->num == max_nodes) | 
					
						
							| 
									
										
										
										
											2017-08-17 08:10:07 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!sk_reserve(st, 1, 0)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  |     if ((loc >= st->num) || (loc < 0)) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         st->data[st->num] = data; | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |         memmove(&st->data[loc + 1], &st->data[loc], | 
					
						
							|  |  |  |                 sizeof(st->data[0]) * (st->num - loc)); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         st->data[loc] = data; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     st->num++; | 
					
						
							|  |  |  |     st->sorted = 0; | 
					
						
							| 
									
										
										
										
											2016-09-08 18:06:29 +08:00
										 |  |  |     return st->num; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  | static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const void *ret = st->data[loc]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (loc != st->num - 1) | 
					
						
							|  |  |  |          memmove(&st->data[loc], &st->data[loc + 1], | 
					
						
							|  |  |  |                  sizeof(st->data[0]) * (st->num - loc - 1)); | 
					
						
							|  |  |  |     st->num--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (void *)ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 23:31:09 +08:00
										 |  |  | void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     for (i = 0; i < st->num; i++) | 
					
						
							|  |  |  |         if (st->data[i] == p) | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |             return internal_delete(st, i); | 
					
						
							| 
									
										
										
										
											2016-05-21 23:31:09 +08:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || loc < 0 || loc >= st->num) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |     return internal_delete(st, loc); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 23:31:09 +08:00
										 |  |  | static int internal_find(OPENSSL_STACK *st, const void *data, | 
					
						
							|  |  |  |                          int ret_val_options) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |     const void *r; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || st->num == 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (st->comp == NULL) { | 
					
						
							|  |  |  |         for (i = 0; i < st->num; i++) | 
					
						
							|  |  |  |             if (st->data[i] == data) | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |                 return i; | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!st->sorted) { | 
					
						
							|  |  |  |         if (st->num > 1) | 
					
						
							|  |  |  |             qsort(st->data, st->num, sizeof(void *), st->comp); | 
					
						
							|  |  |  |         st->sorted = 1; /* empty or single-element stack is considered sorted */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (data == NULL) | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp, | 
					
						
							|  |  |  |                         ret_val_options); | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return r == NULL ? -1 : (int)((const void **)r - st->data); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2003-04-30 04:30:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 23:31:09 +08:00
										 |  |  | int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-21 23:31:09 +08:00
										 |  |  | int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  | int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |     return OPENSSL_sk_insert(st, data, st->num); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  | int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |     return OPENSSL_sk_insert(st, data, 0); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_sk_shift(OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |     if (st == NULL || st->num == 0) | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     return internal_delete(st, 0); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_sk_pop(OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |     if (st == NULL || st->num == 0) | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     return internal_delete(st, st->num - 1); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_sk_zero(OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || st->num == 0) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-05-05 06:00:15 +08:00
										 |  |  |     memset(st->data, 0, sizeof(*st->data) * st->num); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     st->num = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (st == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     for (i = 0; i < st->num; i++) | 
					
						
							|  |  |  |         if (st->data[i] != NULL) | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |             func((char *)st->data[i]); | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  |     OPENSSL_sk_free(st); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_sk_free(OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (st == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2015-05-01 22:02:07 +08:00
										 |  |  |     OPENSSL_free(st->data); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     OPENSSL_free(st); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1998-12-21 18:52:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | int OPENSSL_sk_num(const OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |     return st == NULL ? -1 : st->num; | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i) | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || i < 0 || i >= st->num) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |     return (void *)st->data[i]; | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  | void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data) | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st == NULL || i < 0 || i >= st->num) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |     st->data[i] = data; | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |     st->sorted = 0; | 
					
						
							| 
									
										
										
										
											2016-08-05 04:50:19 +08:00
										 |  |  |     return (void *)st->data[i]; | 
					
						
							| 
									
										
										
										
											1999-05-19 20:45:16 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1999-05-30 23:25:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | void OPENSSL_sk_sort(OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     if (st != NULL && !st->sorted && st->comp != NULL) { | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |         if (st->num > 1) | 
					
						
							| 
									
										
										
										
											2017-09-29 04:03:26 +08:00
										 |  |  |             qsort(st->data, st->num, sizeof(void *), st->comp); | 
					
						
							| 
									
										
										
										
											2017-10-03 19:39:53 +08:00
										 |  |  |         st->sorted = 1; /* empty or single-element stack is considered sorted */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-10-05 00:30:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 22:46:29 +08:00
										 |  |  | int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-08 23:53:36 +08:00
										 |  |  |     return st == NULL ? 1 : st->sorted; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | } |