1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (C) 1995-1998 Eric Young ([email protected])
2*8fb009dcSAndroid Build Coastguard Worker * All rights reserved.
3*8fb009dcSAndroid Build Coastguard Worker *
4*8fb009dcSAndroid Build Coastguard Worker * This package is an SSL implementation written
5*8fb009dcSAndroid Build Coastguard Worker * by Eric Young ([email protected]).
6*8fb009dcSAndroid Build Coastguard Worker * The implementation was written so as to conform with Netscapes SSL.
7*8fb009dcSAndroid Build Coastguard Worker *
8*8fb009dcSAndroid Build Coastguard Worker * This library is free for commercial and non-commercial use as long as
9*8fb009dcSAndroid Build Coastguard Worker * the following conditions are aheared to. The following conditions
10*8fb009dcSAndroid Build Coastguard Worker * apply to all code found in this distribution, be it the RC4, RSA,
11*8fb009dcSAndroid Build Coastguard Worker * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12*8fb009dcSAndroid Build Coastguard Worker * included with this distribution is covered by the same copyright terms
13*8fb009dcSAndroid Build Coastguard Worker * except that the holder is Tim Hudson ([email protected]).
14*8fb009dcSAndroid Build Coastguard Worker *
15*8fb009dcSAndroid Build Coastguard Worker * Copyright remains Eric Young's, and as such any Copyright notices in
16*8fb009dcSAndroid Build Coastguard Worker * the code are not to be removed.
17*8fb009dcSAndroid Build Coastguard Worker * If this package is used in a product, Eric Young should be given attribution
18*8fb009dcSAndroid Build Coastguard Worker * as the author of the parts of the library used.
19*8fb009dcSAndroid Build Coastguard Worker * This can be in the form of a textual message at program startup or
20*8fb009dcSAndroid Build Coastguard Worker * in documentation (online or textual) provided with the package.
21*8fb009dcSAndroid Build Coastguard Worker *
22*8fb009dcSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
23*8fb009dcSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
24*8fb009dcSAndroid Build Coastguard Worker * are met:
25*8fb009dcSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the copyright
26*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
27*8fb009dcSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
28*8fb009dcSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
29*8fb009dcSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
30*8fb009dcSAndroid Build Coastguard Worker * 3. All advertising materials mentioning features or use of this software
31*8fb009dcSAndroid Build Coastguard Worker * must display the following acknowledgement:
32*8fb009dcSAndroid Build Coastguard Worker * "This product includes cryptographic software written by
33*8fb009dcSAndroid Build Coastguard Worker * Eric Young ([email protected])"
34*8fb009dcSAndroid Build Coastguard Worker * The word 'cryptographic' can be left out if the rouines from the library
35*8fb009dcSAndroid Build Coastguard Worker * being used are not cryptographic related :-).
36*8fb009dcSAndroid Build Coastguard Worker * 4. If you include any Windows specific code (or a derivative thereof) from
37*8fb009dcSAndroid Build Coastguard Worker * the apps directory (application code) you must include an acknowledgement:
38*8fb009dcSAndroid Build Coastguard Worker * "This product includes software written by Tim Hudson ([email protected])"
39*8fb009dcSAndroid Build Coastguard Worker *
40*8fb009dcSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41*8fb009dcSAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42*8fb009dcSAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43*8fb009dcSAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44*8fb009dcSAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45*8fb009dcSAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46*8fb009dcSAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*8fb009dcSAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48*8fb009dcSAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49*8fb009dcSAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50*8fb009dcSAndroid Build Coastguard Worker * SUCH DAMAGE.
51*8fb009dcSAndroid Build Coastguard Worker *
52*8fb009dcSAndroid Build Coastguard Worker * The licence and distribution terms for any publically available version or
53*8fb009dcSAndroid Build Coastguard Worker * derivative of this code cannot be changed. i.e. this code cannot simply be
54*8fb009dcSAndroid Build Coastguard Worker * copied and put under another distribution licence
55*8fb009dcSAndroid Build Coastguard Worker * [including the GNU Public Licence.] */
56*8fb009dcSAndroid Build Coastguard Worker
57*8fb009dcSAndroid Build Coastguard Worker #include <openssl/stack.h>
58*8fb009dcSAndroid Build Coastguard Worker
59*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
60*8fb009dcSAndroid Build Coastguard Worker #include <limits.h>
61*8fb009dcSAndroid Build Coastguard Worker
62*8fb009dcSAndroid Build Coastguard Worker #include <openssl/err.h>
63*8fb009dcSAndroid Build Coastguard Worker #include <openssl/mem.h>
64*8fb009dcSAndroid Build Coastguard Worker
65*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
66*8fb009dcSAndroid Build Coastguard Worker
67*8fb009dcSAndroid Build Coastguard Worker
68*8fb009dcSAndroid Build Coastguard Worker struct stack_st {
69*8fb009dcSAndroid Build Coastguard Worker // num contains the number of valid pointers in |data|.
70*8fb009dcSAndroid Build Coastguard Worker size_t num;
71*8fb009dcSAndroid Build Coastguard Worker void **data;
72*8fb009dcSAndroid Build Coastguard Worker // sorted is non-zero if the values pointed to by |data| are in ascending
73*8fb009dcSAndroid Build Coastguard Worker // order, based on |comp|.
74*8fb009dcSAndroid Build Coastguard Worker int sorted;
75*8fb009dcSAndroid Build Coastguard Worker // num_alloc contains the number of pointers allocated in the buffer pointed
76*8fb009dcSAndroid Build Coastguard Worker // to by |data|, which may be larger than |num|.
77*8fb009dcSAndroid Build Coastguard Worker size_t num_alloc;
78*8fb009dcSAndroid Build Coastguard Worker // comp is an optional comparison function.
79*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_cmp_func comp;
80*8fb009dcSAndroid Build Coastguard Worker };
81*8fb009dcSAndroid Build Coastguard Worker
82*8fb009dcSAndroid Build Coastguard Worker // kMinSize is the number of pointers that will be initially allocated in a new
83*8fb009dcSAndroid Build Coastguard Worker // stack.
84*8fb009dcSAndroid Build Coastguard Worker static const size_t kMinSize = 4;
85*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_new(OPENSSL_sk_cmp_func comp)86*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_cmp_func comp) {
87*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *ret = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
88*8fb009dcSAndroid Build Coastguard Worker if (ret == NULL) {
89*8fb009dcSAndroid Build Coastguard Worker return NULL;
90*8fb009dcSAndroid Build Coastguard Worker }
91*8fb009dcSAndroid Build Coastguard Worker
92*8fb009dcSAndroid Build Coastguard Worker ret->data = OPENSSL_calloc(kMinSize, sizeof(void *));
93*8fb009dcSAndroid Build Coastguard Worker if (ret->data == NULL) {
94*8fb009dcSAndroid Build Coastguard Worker goto err;
95*8fb009dcSAndroid Build Coastguard Worker }
96*8fb009dcSAndroid Build Coastguard Worker
97*8fb009dcSAndroid Build Coastguard Worker ret->comp = comp;
98*8fb009dcSAndroid Build Coastguard Worker ret->num_alloc = kMinSize;
99*8fb009dcSAndroid Build Coastguard Worker
100*8fb009dcSAndroid Build Coastguard Worker return ret;
101*8fb009dcSAndroid Build Coastguard Worker
102*8fb009dcSAndroid Build Coastguard Worker err:
103*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(ret);
104*8fb009dcSAndroid Build Coastguard Worker return NULL;
105*8fb009dcSAndroid Build Coastguard Worker }
106*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_new_null(void)107*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *OPENSSL_sk_new_null(void) { return OPENSSL_sk_new(NULL); }
108*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_num(const OPENSSL_STACK * sk)109*8fb009dcSAndroid Build Coastguard Worker size_t OPENSSL_sk_num(const OPENSSL_STACK *sk) {
110*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
111*8fb009dcSAndroid Build Coastguard Worker return 0;
112*8fb009dcSAndroid Build Coastguard Worker }
113*8fb009dcSAndroid Build Coastguard Worker return sk->num;
114*8fb009dcSAndroid Build Coastguard Worker }
115*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_zero(OPENSSL_STACK * sk)116*8fb009dcSAndroid Build Coastguard Worker void OPENSSL_sk_zero(OPENSSL_STACK *sk) {
117*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL || sk->num == 0) {
118*8fb009dcSAndroid Build Coastguard Worker return;
119*8fb009dcSAndroid Build Coastguard Worker }
120*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(sk->data, 0, sizeof(void*) * sk->num);
121*8fb009dcSAndroid Build Coastguard Worker sk->num = 0;
122*8fb009dcSAndroid Build Coastguard Worker sk->sorted = 0;
123*8fb009dcSAndroid Build Coastguard Worker }
124*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_value(const OPENSSL_STACK * sk,size_t i)125*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_value(const OPENSSL_STACK *sk, size_t i) {
126*8fb009dcSAndroid Build Coastguard Worker if (!sk || i >= sk->num) {
127*8fb009dcSAndroid Build Coastguard Worker return NULL;
128*8fb009dcSAndroid Build Coastguard Worker }
129*8fb009dcSAndroid Build Coastguard Worker return sk->data[i];
130*8fb009dcSAndroid Build Coastguard Worker }
131*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_set(OPENSSL_STACK * sk,size_t i,void * value)132*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_set(OPENSSL_STACK *sk, size_t i, void *value) {
133*8fb009dcSAndroid Build Coastguard Worker if (!sk || i >= sk->num) {
134*8fb009dcSAndroid Build Coastguard Worker return NULL;
135*8fb009dcSAndroid Build Coastguard Worker }
136*8fb009dcSAndroid Build Coastguard Worker return sk->data[i] = value;
137*8fb009dcSAndroid Build Coastguard Worker }
138*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_free(OPENSSL_STACK * sk)139*8fb009dcSAndroid Build Coastguard Worker void OPENSSL_sk_free(OPENSSL_STACK *sk) {
140*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
141*8fb009dcSAndroid Build Coastguard Worker return;
142*8fb009dcSAndroid Build Coastguard Worker }
143*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(sk->data);
144*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(sk);
145*8fb009dcSAndroid Build Coastguard Worker }
146*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_pop_free_ex(OPENSSL_STACK * sk,OPENSSL_sk_call_free_func call_free_func,OPENSSL_sk_free_func free_func)147*8fb009dcSAndroid Build Coastguard Worker void OPENSSL_sk_pop_free_ex(OPENSSL_STACK *sk,
148*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_free_func call_free_func,
149*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free_func free_func) {
150*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
151*8fb009dcSAndroid Build Coastguard Worker return;
152*8fb009dcSAndroid Build Coastguard Worker }
153*8fb009dcSAndroid Build Coastguard Worker
154*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sk->num; i++) {
155*8fb009dcSAndroid Build Coastguard Worker if (sk->data[i] != NULL) {
156*8fb009dcSAndroid Build Coastguard Worker call_free_func(free_func, sk->data[i]);
157*8fb009dcSAndroid Build Coastguard Worker }
158*8fb009dcSAndroid Build Coastguard Worker }
159*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free(sk);
160*8fb009dcSAndroid Build Coastguard Worker }
161*8fb009dcSAndroid Build Coastguard Worker
162*8fb009dcSAndroid Build Coastguard Worker // Historically, |sk_pop_free| called the function as |OPENSSL_sk_free_func|
163*8fb009dcSAndroid Build Coastguard Worker // directly. This is undefined in C. Some callers called |sk_pop_free| directly,
164*8fb009dcSAndroid Build Coastguard Worker // so we must maintain a compatibility version for now.
call_free_func_legacy(OPENSSL_sk_free_func func,void * ptr)165*8fb009dcSAndroid Build Coastguard Worker static void call_free_func_legacy(OPENSSL_sk_free_func func, void *ptr) {
166*8fb009dcSAndroid Build Coastguard Worker func(ptr);
167*8fb009dcSAndroid Build Coastguard Worker }
168*8fb009dcSAndroid Build Coastguard Worker
sk_pop_free(OPENSSL_STACK * sk,OPENSSL_sk_free_func free_func)169*8fb009dcSAndroid Build Coastguard Worker void sk_pop_free(OPENSSL_STACK *sk, OPENSSL_sk_free_func free_func) {
170*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_pop_free_ex(sk, call_free_func_legacy, free_func);
171*8fb009dcSAndroid Build Coastguard Worker }
172*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_insert(OPENSSL_STACK * sk,void * p,size_t where)173*8fb009dcSAndroid Build Coastguard Worker size_t OPENSSL_sk_insert(OPENSSL_STACK *sk, void *p, size_t where) {
174*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
175*8fb009dcSAndroid Build Coastguard Worker return 0;
176*8fb009dcSAndroid Build Coastguard Worker }
177*8fb009dcSAndroid Build Coastguard Worker
178*8fb009dcSAndroid Build Coastguard Worker if (sk->num >= INT_MAX) {
179*8fb009dcSAndroid Build Coastguard Worker OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW);
180*8fb009dcSAndroid Build Coastguard Worker return 0;
181*8fb009dcSAndroid Build Coastguard Worker }
182*8fb009dcSAndroid Build Coastguard Worker
183*8fb009dcSAndroid Build Coastguard Worker if (sk->num_alloc <= sk->num + 1) {
184*8fb009dcSAndroid Build Coastguard Worker // Attempt to double the size of the array.
185*8fb009dcSAndroid Build Coastguard Worker size_t new_alloc = sk->num_alloc << 1;
186*8fb009dcSAndroid Build Coastguard Worker size_t alloc_size = new_alloc * sizeof(void *);
187*8fb009dcSAndroid Build Coastguard Worker void **data;
188*8fb009dcSAndroid Build Coastguard Worker
189*8fb009dcSAndroid Build Coastguard Worker // If the doubling overflowed, try to increment.
190*8fb009dcSAndroid Build Coastguard Worker if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) {
191*8fb009dcSAndroid Build Coastguard Worker new_alloc = sk->num_alloc + 1;
192*8fb009dcSAndroid Build Coastguard Worker alloc_size = new_alloc * sizeof(void *);
193*8fb009dcSAndroid Build Coastguard Worker }
194*8fb009dcSAndroid Build Coastguard Worker
195*8fb009dcSAndroid Build Coastguard Worker // If the increment also overflowed, fail.
196*8fb009dcSAndroid Build Coastguard Worker if (new_alloc < sk->num_alloc || alloc_size / sizeof(void *) != new_alloc) {
197*8fb009dcSAndroid Build Coastguard Worker return 0;
198*8fb009dcSAndroid Build Coastguard Worker }
199*8fb009dcSAndroid Build Coastguard Worker
200*8fb009dcSAndroid Build Coastguard Worker data = OPENSSL_realloc(sk->data, alloc_size);
201*8fb009dcSAndroid Build Coastguard Worker if (data == NULL) {
202*8fb009dcSAndroid Build Coastguard Worker return 0;
203*8fb009dcSAndroid Build Coastguard Worker }
204*8fb009dcSAndroid Build Coastguard Worker
205*8fb009dcSAndroid Build Coastguard Worker sk->data = data;
206*8fb009dcSAndroid Build Coastguard Worker sk->num_alloc = new_alloc;
207*8fb009dcSAndroid Build Coastguard Worker }
208*8fb009dcSAndroid Build Coastguard Worker
209*8fb009dcSAndroid Build Coastguard Worker if (where >= sk->num) {
210*8fb009dcSAndroid Build Coastguard Worker sk->data[sk->num] = p;
211*8fb009dcSAndroid Build Coastguard Worker } else {
212*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memmove(&sk->data[where + 1], &sk->data[where],
213*8fb009dcSAndroid Build Coastguard Worker sizeof(void *) * (sk->num - where));
214*8fb009dcSAndroid Build Coastguard Worker sk->data[where] = p;
215*8fb009dcSAndroid Build Coastguard Worker }
216*8fb009dcSAndroid Build Coastguard Worker
217*8fb009dcSAndroid Build Coastguard Worker sk->num++;
218*8fb009dcSAndroid Build Coastguard Worker sk->sorted = 0;
219*8fb009dcSAndroid Build Coastguard Worker
220*8fb009dcSAndroid Build Coastguard Worker return sk->num;
221*8fb009dcSAndroid Build Coastguard Worker }
222*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_delete(OPENSSL_STACK * sk,size_t where)223*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_delete(OPENSSL_STACK *sk, size_t where) {
224*8fb009dcSAndroid Build Coastguard Worker void *ret;
225*8fb009dcSAndroid Build Coastguard Worker
226*8fb009dcSAndroid Build Coastguard Worker if (!sk || where >= sk->num) {
227*8fb009dcSAndroid Build Coastguard Worker return NULL;
228*8fb009dcSAndroid Build Coastguard Worker }
229*8fb009dcSAndroid Build Coastguard Worker
230*8fb009dcSAndroid Build Coastguard Worker ret = sk->data[where];
231*8fb009dcSAndroid Build Coastguard Worker
232*8fb009dcSAndroid Build Coastguard Worker if (where != sk->num - 1) {
233*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memmove(&sk->data[where], &sk->data[where + 1],
234*8fb009dcSAndroid Build Coastguard Worker sizeof(void *) * (sk->num - where - 1));
235*8fb009dcSAndroid Build Coastguard Worker }
236*8fb009dcSAndroid Build Coastguard Worker
237*8fb009dcSAndroid Build Coastguard Worker sk->num--;
238*8fb009dcSAndroid Build Coastguard Worker return ret;
239*8fb009dcSAndroid Build Coastguard Worker }
240*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_delete_ptr(OPENSSL_STACK * sk,const void * p)241*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *sk, const void *p) {
242*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
243*8fb009dcSAndroid Build Coastguard Worker return NULL;
244*8fb009dcSAndroid Build Coastguard Worker }
245*8fb009dcSAndroid Build Coastguard Worker
246*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sk->num; i++) {
247*8fb009dcSAndroid Build Coastguard Worker if (sk->data[i] == p) {
248*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_sk_delete(sk, i);
249*8fb009dcSAndroid Build Coastguard Worker }
250*8fb009dcSAndroid Build Coastguard Worker }
251*8fb009dcSAndroid Build Coastguard Worker
252*8fb009dcSAndroid Build Coastguard Worker return NULL;
253*8fb009dcSAndroid Build Coastguard Worker }
254*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_delete_if(OPENSSL_STACK * sk,OPENSSL_sk_call_delete_if_func call_func,OPENSSL_sk_delete_if_func func,void * data)255*8fb009dcSAndroid Build Coastguard Worker void OPENSSL_sk_delete_if(OPENSSL_STACK *sk,
256*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_delete_if_func call_func,
257*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_delete_if_func func, void *data) {
258*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
259*8fb009dcSAndroid Build Coastguard Worker return;
260*8fb009dcSAndroid Build Coastguard Worker }
261*8fb009dcSAndroid Build Coastguard Worker
262*8fb009dcSAndroid Build Coastguard Worker size_t new_num = 0;
263*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sk->num; i++) {
264*8fb009dcSAndroid Build Coastguard Worker if (!call_func(func, sk->data[i], data)) {
265*8fb009dcSAndroid Build Coastguard Worker sk->data[new_num] = sk->data[i];
266*8fb009dcSAndroid Build Coastguard Worker new_num++;
267*8fb009dcSAndroid Build Coastguard Worker }
268*8fb009dcSAndroid Build Coastguard Worker }
269*8fb009dcSAndroid Build Coastguard Worker sk->num = new_num;
270*8fb009dcSAndroid Build Coastguard Worker }
271*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_find(const OPENSSL_STACK * sk,size_t * out_index,const void * p,OPENSSL_sk_call_cmp_func call_cmp_func)272*8fb009dcSAndroid Build Coastguard Worker int OPENSSL_sk_find(const OPENSSL_STACK *sk, size_t *out_index, const void *p,
273*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_cmp_func call_cmp_func) {
274*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
275*8fb009dcSAndroid Build Coastguard Worker return 0;
276*8fb009dcSAndroid Build Coastguard Worker }
277*8fb009dcSAndroid Build Coastguard Worker
278*8fb009dcSAndroid Build Coastguard Worker if (sk->comp == NULL) {
279*8fb009dcSAndroid Build Coastguard Worker // Use pointer equality when no comparison function has been set.
280*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sk->num; i++) {
281*8fb009dcSAndroid Build Coastguard Worker if (sk->data[i] == p) {
282*8fb009dcSAndroid Build Coastguard Worker if (out_index) {
283*8fb009dcSAndroid Build Coastguard Worker *out_index = i;
284*8fb009dcSAndroid Build Coastguard Worker }
285*8fb009dcSAndroid Build Coastguard Worker return 1;
286*8fb009dcSAndroid Build Coastguard Worker }
287*8fb009dcSAndroid Build Coastguard Worker }
288*8fb009dcSAndroid Build Coastguard Worker return 0;
289*8fb009dcSAndroid Build Coastguard Worker }
290*8fb009dcSAndroid Build Coastguard Worker
291*8fb009dcSAndroid Build Coastguard Worker if (p == NULL) {
292*8fb009dcSAndroid Build Coastguard Worker return 0;
293*8fb009dcSAndroid Build Coastguard Worker }
294*8fb009dcSAndroid Build Coastguard Worker
295*8fb009dcSAndroid Build Coastguard Worker if (!OPENSSL_sk_is_sorted(sk)) {
296*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sk->num; i++) {
297*8fb009dcSAndroid Build Coastguard Worker if (call_cmp_func(sk->comp, p, sk->data[i]) == 0) {
298*8fb009dcSAndroid Build Coastguard Worker if (out_index) {
299*8fb009dcSAndroid Build Coastguard Worker *out_index = i;
300*8fb009dcSAndroid Build Coastguard Worker }
301*8fb009dcSAndroid Build Coastguard Worker return 1;
302*8fb009dcSAndroid Build Coastguard Worker }
303*8fb009dcSAndroid Build Coastguard Worker }
304*8fb009dcSAndroid Build Coastguard Worker return 0;
305*8fb009dcSAndroid Build Coastguard Worker }
306*8fb009dcSAndroid Build Coastguard Worker
307*8fb009dcSAndroid Build Coastguard Worker // The stack is sorted, so binary search to find the element.
308*8fb009dcSAndroid Build Coastguard Worker //
309*8fb009dcSAndroid Build Coastguard Worker // |lo| and |hi| maintain a half-open interval of where the answer may be. All
310*8fb009dcSAndroid Build Coastguard Worker // indices such that |lo <= idx < hi| are candidates.
311*8fb009dcSAndroid Build Coastguard Worker size_t lo = 0, hi = sk->num;
312*8fb009dcSAndroid Build Coastguard Worker while (lo < hi) {
313*8fb009dcSAndroid Build Coastguard Worker // Bias |mid| towards |lo|. See the |r == 0| case below.
314*8fb009dcSAndroid Build Coastguard Worker size_t mid = lo + (hi - lo - 1) / 2;
315*8fb009dcSAndroid Build Coastguard Worker assert(lo <= mid && mid < hi);
316*8fb009dcSAndroid Build Coastguard Worker int r = call_cmp_func(sk->comp, p, sk->data[mid]);
317*8fb009dcSAndroid Build Coastguard Worker if (r > 0) {
318*8fb009dcSAndroid Build Coastguard Worker lo = mid + 1; // |mid| is too low.
319*8fb009dcSAndroid Build Coastguard Worker } else if (r < 0) {
320*8fb009dcSAndroid Build Coastguard Worker hi = mid; // |mid| is too high.
321*8fb009dcSAndroid Build Coastguard Worker } else {
322*8fb009dcSAndroid Build Coastguard Worker // |mid| matches. However, this function returns the earliest match, so we
323*8fb009dcSAndroid Build Coastguard Worker // can only return if the range has size one.
324*8fb009dcSAndroid Build Coastguard Worker if (hi - lo == 1) {
325*8fb009dcSAndroid Build Coastguard Worker if (out_index != NULL) {
326*8fb009dcSAndroid Build Coastguard Worker *out_index = mid;
327*8fb009dcSAndroid Build Coastguard Worker }
328*8fb009dcSAndroid Build Coastguard Worker return 1;
329*8fb009dcSAndroid Build Coastguard Worker }
330*8fb009dcSAndroid Build Coastguard Worker // The sample is biased towards |lo|. |mid| can only be |hi - 1| if
331*8fb009dcSAndroid Build Coastguard Worker // |hi - lo| was one, so this makes forward progress.
332*8fb009dcSAndroid Build Coastguard Worker assert(mid + 1 < hi);
333*8fb009dcSAndroid Build Coastguard Worker hi = mid + 1;
334*8fb009dcSAndroid Build Coastguard Worker }
335*8fb009dcSAndroid Build Coastguard Worker }
336*8fb009dcSAndroid Build Coastguard Worker
337*8fb009dcSAndroid Build Coastguard Worker assert(lo == hi);
338*8fb009dcSAndroid Build Coastguard Worker return 0; // Not found.
339*8fb009dcSAndroid Build Coastguard Worker }
340*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_shift(OPENSSL_STACK * sk)341*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_shift(OPENSSL_STACK *sk) {
342*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
343*8fb009dcSAndroid Build Coastguard Worker return NULL;
344*8fb009dcSAndroid Build Coastguard Worker }
345*8fb009dcSAndroid Build Coastguard Worker if (sk->num == 0) {
346*8fb009dcSAndroid Build Coastguard Worker return NULL;
347*8fb009dcSAndroid Build Coastguard Worker }
348*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_sk_delete(sk, 0);
349*8fb009dcSAndroid Build Coastguard Worker }
350*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_push(OPENSSL_STACK * sk,void * p)351*8fb009dcSAndroid Build Coastguard Worker size_t OPENSSL_sk_push(OPENSSL_STACK *sk, void *p) {
352*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_sk_insert(sk, p, sk->num);
353*8fb009dcSAndroid Build Coastguard Worker }
354*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_pop(OPENSSL_STACK * sk)355*8fb009dcSAndroid Build Coastguard Worker void *OPENSSL_sk_pop(OPENSSL_STACK *sk) {
356*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
357*8fb009dcSAndroid Build Coastguard Worker return NULL;
358*8fb009dcSAndroid Build Coastguard Worker }
359*8fb009dcSAndroid Build Coastguard Worker if (sk->num == 0) {
360*8fb009dcSAndroid Build Coastguard Worker return NULL;
361*8fb009dcSAndroid Build Coastguard Worker }
362*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_sk_delete(sk, sk->num - 1);
363*8fb009dcSAndroid Build Coastguard Worker }
364*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_dup(const OPENSSL_STACK * sk)365*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) {
366*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL) {
367*8fb009dcSAndroid Build Coastguard Worker return NULL;
368*8fb009dcSAndroid Build Coastguard Worker }
369*8fb009dcSAndroid Build Coastguard Worker
370*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *ret = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
371*8fb009dcSAndroid Build Coastguard Worker if (ret == NULL) {
372*8fb009dcSAndroid Build Coastguard Worker return NULL;
373*8fb009dcSAndroid Build Coastguard Worker }
374*8fb009dcSAndroid Build Coastguard Worker
375*8fb009dcSAndroid Build Coastguard Worker ret->data = OPENSSL_memdup(sk->data, sizeof(void *) * sk->num_alloc);
376*8fb009dcSAndroid Build Coastguard Worker if (ret->data == NULL) {
377*8fb009dcSAndroid Build Coastguard Worker goto err;
378*8fb009dcSAndroid Build Coastguard Worker }
379*8fb009dcSAndroid Build Coastguard Worker
380*8fb009dcSAndroid Build Coastguard Worker ret->num = sk->num;
381*8fb009dcSAndroid Build Coastguard Worker ret->sorted = sk->sorted;
382*8fb009dcSAndroid Build Coastguard Worker ret->num_alloc = sk->num_alloc;
383*8fb009dcSAndroid Build Coastguard Worker ret->comp = sk->comp;
384*8fb009dcSAndroid Build Coastguard Worker return ret;
385*8fb009dcSAndroid Build Coastguard Worker
386*8fb009dcSAndroid Build Coastguard Worker err:
387*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free(ret);
388*8fb009dcSAndroid Build Coastguard Worker return NULL;
389*8fb009dcSAndroid Build Coastguard Worker }
390*8fb009dcSAndroid Build Coastguard Worker
parent_idx(size_t idx)391*8fb009dcSAndroid Build Coastguard Worker static size_t parent_idx(size_t idx) {
392*8fb009dcSAndroid Build Coastguard Worker assert(idx > 0);
393*8fb009dcSAndroid Build Coastguard Worker return (idx - 1) / 2;
394*8fb009dcSAndroid Build Coastguard Worker }
395*8fb009dcSAndroid Build Coastguard Worker
left_idx(size_t idx)396*8fb009dcSAndroid Build Coastguard Worker static size_t left_idx(size_t idx) {
397*8fb009dcSAndroid Build Coastguard Worker // The largest possible index is |PTRDIFF_MAX|, not |SIZE_MAX|. If
398*8fb009dcSAndroid Build Coastguard Worker // |ptrdiff_t|, a signed type, is the same size as |size_t|, this cannot
399*8fb009dcSAndroid Build Coastguard Worker // overflow.
400*8fb009dcSAndroid Build Coastguard Worker assert(idx <= PTRDIFF_MAX);
401*8fb009dcSAndroid Build Coastguard Worker static_assert(PTRDIFF_MAX <= (SIZE_MAX - 1) / 2, "2 * idx + 1 may oveflow");
402*8fb009dcSAndroid Build Coastguard Worker return 2 * idx + 1;
403*8fb009dcSAndroid Build Coastguard Worker }
404*8fb009dcSAndroid Build Coastguard Worker
405*8fb009dcSAndroid Build Coastguard Worker // down_heap fixes the subtree rooted at |i|. |i|'s children must each satisfy
406*8fb009dcSAndroid Build Coastguard Worker // the heap property. Only the first |num| elements of |sk| are considered.
down_heap(OPENSSL_STACK * sk,OPENSSL_sk_call_cmp_func call_cmp_func,size_t i,size_t num)407*8fb009dcSAndroid Build Coastguard Worker static void down_heap(OPENSSL_STACK *sk, OPENSSL_sk_call_cmp_func call_cmp_func,
408*8fb009dcSAndroid Build Coastguard Worker size_t i, size_t num) {
409*8fb009dcSAndroid Build Coastguard Worker assert(i < num && num <= sk->num);
410*8fb009dcSAndroid Build Coastguard Worker for (;;) {
411*8fb009dcSAndroid Build Coastguard Worker size_t left = left_idx(i);
412*8fb009dcSAndroid Build Coastguard Worker if (left >= num) {
413*8fb009dcSAndroid Build Coastguard Worker break; // No left child.
414*8fb009dcSAndroid Build Coastguard Worker }
415*8fb009dcSAndroid Build Coastguard Worker
416*8fb009dcSAndroid Build Coastguard Worker // Swap |i| with the largest of its children.
417*8fb009dcSAndroid Build Coastguard Worker size_t next = i;
418*8fb009dcSAndroid Build Coastguard Worker if (call_cmp_func(sk->comp, sk->data[next], sk->data[left]) < 0) {
419*8fb009dcSAndroid Build Coastguard Worker next = left;
420*8fb009dcSAndroid Build Coastguard Worker }
421*8fb009dcSAndroid Build Coastguard Worker size_t right = left + 1; // Cannot overflow because |left < num|.
422*8fb009dcSAndroid Build Coastguard Worker if (right < num &&
423*8fb009dcSAndroid Build Coastguard Worker call_cmp_func(sk->comp, sk->data[next], sk->data[right]) < 0) {
424*8fb009dcSAndroid Build Coastguard Worker next = right;
425*8fb009dcSAndroid Build Coastguard Worker }
426*8fb009dcSAndroid Build Coastguard Worker
427*8fb009dcSAndroid Build Coastguard Worker if (i == next) {
428*8fb009dcSAndroid Build Coastguard Worker break; // |i| is already larger than its children.
429*8fb009dcSAndroid Build Coastguard Worker }
430*8fb009dcSAndroid Build Coastguard Worker
431*8fb009dcSAndroid Build Coastguard Worker void *tmp = sk->data[i];
432*8fb009dcSAndroid Build Coastguard Worker sk->data[i] = sk->data[next];
433*8fb009dcSAndroid Build Coastguard Worker sk->data[next] = tmp;
434*8fb009dcSAndroid Build Coastguard Worker i = next;
435*8fb009dcSAndroid Build Coastguard Worker }
436*8fb009dcSAndroid Build Coastguard Worker }
437*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_sort(OPENSSL_STACK * sk,OPENSSL_sk_call_cmp_func call_cmp_func)438*8fb009dcSAndroid Build Coastguard Worker void OPENSSL_sk_sort(OPENSSL_STACK *sk,
439*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_cmp_func call_cmp_func) {
440*8fb009dcSAndroid Build Coastguard Worker if (sk == NULL || sk->comp == NULL || sk->sorted) {
441*8fb009dcSAndroid Build Coastguard Worker return;
442*8fb009dcSAndroid Build Coastguard Worker }
443*8fb009dcSAndroid Build Coastguard Worker
444*8fb009dcSAndroid Build Coastguard Worker if (sk->num >= 2) {
445*8fb009dcSAndroid Build Coastguard Worker // |qsort| lacks a context parameter in the comparison function for us to
446*8fb009dcSAndroid Build Coastguard Worker // pass in |call_cmp_func| and |sk->comp|. While we could cast |sk->comp| to
447*8fb009dcSAndroid Build Coastguard Worker // the expected type, it is undefined behavior in C can trip sanitizers.
448*8fb009dcSAndroid Build Coastguard Worker // |qsort_r| and |qsort_s| avoid this, but using them is impractical. See
449*8fb009dcSAndroid Build Coastguard Worker // https://stackoverflow.com/a/39561369
450*8fb009dcSAndroid Build Coastguard Worker //
451*8fb009dcSAndroid Build Coastguard Worker // Use our own heap sort instead. This is not performance-sensitive, so we
452*8fb009dcSAndroid Build Coastguard Worker // optimize for simplicity and size. First, build a max-heap in place.
453*8fb009dcSAndroid Build Coastguard Worker for (size_t i = parent_idx(sk->num - 1); i < sk->num; i--) {
454*8fb009dcSAndroid Build Coastguard Worker down_heap(sk, call_cmp_func, i, sk->num);
455*8fb009dcSAndroid Build Coastguard Worker }
456*8fb009dcSAndroid Build Coastguard Worker
457*8fb009dcSAndroid Build Coastguard Worker // Iteratively remove the maximum element to populate the result in reverse.
458*8fb009dcSAndroid Build Coastguard Worker for (size_t i = sk->num - 1; i > 0; i--) {
459*8fb009dcSAndroid Build Coastguard Worker void *tmp = sk->data[0];
460*8fb009dcSAndroid Build Coastguard Worker sk->data[0] = sk->data[i];
461*8fb009dcSAndroid Build Coastguard Worker sk->data[i] = tmp;
462*8fb009dcSAndroid Build Coastguard Worker down_heap(sk, call_cmp_func, 0, i);
463*8fb009dcSAndroid Build Coastguard Worker }
464*8fb009dcSAndroid Build Coastguard Worker }
465*8fb009dcSAndroid Build Coastguard Worker sk->sorted = 1;
466*8fb009dcSAndroid Build Coastguard Worker }
467*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_is_sorted(const OPENSSL_STACK * sk)468*8fb009dcSAndroid Build Coastguard Worker int OPENSSL_sk_is_sorted(const OPENSSL_STACK *sk) {
469*8fb009dcSAndroid Build Coastguard Worker if (!sk) {
470*8fb009dcSAndroid Build Coastguard Worker return 1;
471*8fb009dcSAndroid Build Coastguard Worker }
472*8fb009dcSAndroid Build Coastguard Worker // Zero- and one-element lists are always sorted.
473*8fb009dcSAndroid Build Coastguard Worker return sk->sorted || (sk->comp != NULL && sk->num < 2);
474*8fb009dcSAndroid Build Coastguard Worker }
475*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_set_cmp_func(OPENSSL_STACK * sk,OPENSSL_sk_cmp_func comp)476*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_cmp_func OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk,
477*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_cmp_func comp) {
478*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_cmp_func old = sk->comp;
479*8fb009dcSAndroid Build Coastguard Worker
480*8fb009dcSAndroid Build Coastguard Worker if (sk->comp != comp) {
481*8fb009dcSAndroid Build Coastguard Worker sk->sorted = 0;
482*8fb009dcSAndroid Build Coastguard Worker }
483*8fb009dcSAndroid Build Coastguard Worker sk->comp = comp;
484*8fb009dcSAndroid Build Coastguard Worker
485*8fb009dcSAndroid Build Coastguard Worker return old;
486*8fb009dcSAndroid Build Coastguard Worker }
487*8fb009dcSAndroid Build Coastguard Worker
OPENSSL_sk_deep_copy(const OPENSSL_STACK * sk,OPENSSL_sk_call_copy_func call_copy_func,OPENSSL_sk_copy_func copy_func,OPENSSL_sk_call_free_func call_free_func,OPENSSL_sk_free_func free_func)488*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
489*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_copy_func call_copy_func,
490*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_copy_func copy_func,
491*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_call_free_func call_free_func,
492*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free_func free_func) {
493*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *ret = OPENSSL_sk_dup(sk);
494*8fb009dcSAndroid Build Coastguard Worker if (ret == NULL) {
495*8fb009dcSAndroid Build Coastguard Worker return NULL;
496*8fb009dcSAndroid Build Coastguard Worker }
497*8fb009dcSAndroid Build Coastguard Worker
498*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < ret->num; i++) {
499*8fb009dcSAndroid Build Coastguard Worker if (ret->data[i] == NULL) {
500*8fb009dcSAndroid Build Coastguard Worker continue;
501*8fb009dcSAndroid Build Coastguard Worker }
502*8fb009dcSAndroid Build Coastguard Worker ret->data[i] = call_copy_func(copy_func, ret->data[i]);
503*8fb009dcSAndroid Build Coastguard Worker if (ret->data[i] == NULL) {
504*8fb009dcSAndroid Build Coastguard Worker for (size_t j = 0; j < i; j++) {
505*8fb009dcSAndroid Build Coastguard Worker if (ret->data[j] != NULL) {
506*8fb009dcSAndroid Build Coastguard Worker call_free_func(free_func, ret->data[j]);
507*8fb009dcSAndroid Build Coastguard Worker }
508*8fb009dcSAndroid Build Coastguard Worker }
509*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free(ret);
510*8fb009dcSAndroid Build Coastguard Worker return NULL;
511*8fb009dcSAndroid Build Coastguard Worker }
512*8fb009dcSAndroid Build Coastguard Worker }
513*8fb009dcSAndroid Build Coastguard Worker
514*8fb009dcSAndroid Build Coastguard Worker return ret;
515*8fb009dcSAndroid Build Coastguard Worker }
516*8fb009dcSAndroid Build Coastguard Worker
sk_new_null(void)517*8fb009dcSAndroid Build Coastguard Worker OPENSSL_STACK *sk_new_null(void) { return OPENSSL_sk_new_null(); }
518*8fb009dcSAndroid Build Coastguard Worker
sk_num(const OPENSSL_STACK * sk)519*8fb009dcSAndroid Build Coastguard Worker size_t sk_num(const OPENSSL_STACK *sk) { return OPENSSL_sk_num(sk); }
520*8fb009dcSAndroid Build Coastguard Worker
sk_value(const OPENSSL_STACK * sk,size_t i)521*8fb009dcSAndroid Build Coastguard Worker void *sk_value(const OPENSSL_STACK *sk, size_t i) {
522*8fb009dcSAndroid Build Coastguard Worker return OPENSSL_sk_value(sk, i);
523*8fb009dcSAndroid Build Coastguard Worker }
524*8fb009dcSAndroid Build Coastguard Worker
sk_free(OPENSSL_STACK * sk)525*8fb009dcSAndroid Build Coastguard Worker void sk_free(OPENSSL_STACK *sk) { OPENSSL_sk_free(sk); }
526*8fb009dcSAndroid Build Coastguard Worker
sk_push(OPENSSL_STACK * sk,void * p)527*8fb009dcSAndroid Build Coastguard Worker size_t sk_push(OPENSSL_STACK *sk, void *p) { return OPENSSL_sk_push(sk, p); }
528*8fb009dcSAndroid Build Coastguard Worker
sk_pop(OPENSSL_STACK * sk)529*8fb009dcSAndroid Build Coastguard Worker void *sk_pop(OPENSSL_STACK *sk) { return OPENSSL_sk_pop(sk); }
530*8fb009dcSAndroid Build Coastguard Worker
sk_pop_free_ex(OPENSSL_STACK * sk,OPENSSL_sk_call_free_func call_free_func,OPENSSL_sk_free_func free_func)531*8fb009dcSAndroid Build Coastguard Worker void sk_pop_free_ex(OPENSSL_STACK *sk, OPENSSL_sk_call_free_func call_free_func,
532*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_free_func free_func) {
533*8fb009dcSAndroid Build Coastguard Worker OPENSSL_sk_pop_free_ex(sk, call_free_func, free_func);
534*8fb009dcSAndroid Build Coastguard Worker }
535