xref: /openssl/crypto/stack/stack.c (revision 7cc5738a)
1 /*
2  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include "internal/numbers.h"
13 #include "internal/safe_math.h"
14 #include <openssl/stack.h>
15 #include <errno.h>
16 #include <openssl/e_os2.h>      /* For ossl_inline */
17 
18 OSSL_SAFE_MATH_SIGNED(int, int)
19 
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
25                              ? (int)(SIZE_MAX / sizeof(void *))
26                              : INT_MAX;
27 
28 struct stack_st {
29     int num;
30     const void **data;
31     int sorted;
32     int num_alloc;
33     OPENSSL_sk_compfunc comp;
34 };
35 
OPENSSL_sk_set_cmp_func(OPENSSL_STACK * sk,OPENSSL_sk_compfunc c)36 OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
37 {
38     OPENSSL_sk_compfunc old = sk->comp;
39 
40     if (sk->comp != c)
41         sk->sorted = 0;
42     sk->comp = c;
43 
44     return old;
45 }
46 
OPENSSL_sk_dup(const OPENSSL_STACK * sk)47 OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
48 {
49     OPENSSL_STACK *ret;
50 
51     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
52         goto err;
53 
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     }
62 
63     if (sk == NULL || sk->num == 0) {
64         /* postpone |ret->data| allocation */
65         ret->data = NULL;
66         ret->num_alloc = 0;
67         return ret;
68     }
69 
70     /* duplicate |sk->data| content */
71     if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)
72         goto err;
73     memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
74     return ret;
75 
76  err:
77     ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
78     OPENSSL_sk_free(ret);
79     return NULL;
80 }
81 
OPENSSL_sk_deep_copy(const OPENSSL_STACK * sk,OPENSSL_sk_copyfunc copy_func,OPENSSL_sk_freefunc free_func)82 OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
83                              OPENSSL_sk_copyfunc copy_func,
84                              OPENSSL_sk_freefunc free_func)
85 {
86     OPENSSL_STACK *ret;
87     int i;
88 
89     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
90         goto err;
91 
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     }
100 
101     if (sk == NULL || sk->num == 0) {
102         /* postpone |ret| data allocation */
103         ret->data = NULL;
104         ret->num_alloc = 0;
105         return ret;
106     }
107 
108     ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
109     ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);
110     if (ret->data == NULL)
111         goto err;
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)
119                     free_func((void *)ret->data[i]);
120             goto err;
121         }
122     }
123     return ret;
124 
125  err:
126     ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
127     OPENSSL_sk_free(ret);
128     return NULL;
129 }
130 
OPENSSL_sk_new_null(void)131 OPENSSL_STACK *OPENSSL_sk_new_null(void)
132 {
133     return OPENSSL_sk_new_reserve(NULL, 0);
134 }
135 
OPENSSL_sk_new(OPENSSL_sk_compfunc c)136 OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
137 {
138     return OPENSSL_sk_new_reserve(c, 0);
139 }
140 
141 /*
142  * Calculate the array growth based on the target size.
143  *
144  * The growth factor is a rational number and is defined by a numerator
145  * and a denominator.  According to Andrew Koenig in his paper "Why Are
146  * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
147  * than the golden ratio (1.618...).
148  *
149  * Considering only the Fibonacci ratios less than the golden ratio, the
150  * number of steps from the minimum allocation to integer overflow is:
151  *      factor  decimal    growths
152  *       3/2     1.5          51
153  *       8/5     1.6          45
154  *      21/13    1.615...     44
155  *
156  * All larger factors have the same number of growths.
157  *
158  * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice.
159  */
compute_growth(int target,int current)160 static ossl_inline int compute_growth(int target, int current)
161 {
162     int err = 0;
163 
164     while (current < target) {
165         if (current >= max_nodes)
166             return 0;
167 
168         current = safe_muldiv_int(current, 8, 5, &err);
169         if (err)
170             return 0;
171         if (current >= max_nodes)
172             current = max_nodes;
173     }
174     return current;
175 }
176 
177 /* internal STACK storage allocation */
sk_reserve(OPENSSL_STACK * st,int n,int exact)178 static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
179 {
180     const void **tmpdata;
181     int num_alloc;
182 
183     /* Check to see the reservation isn't exceeding the hard limit */
184     if (n > max_nodes - st->num)
185         return 0;
186 
187     /* Figure out the new size */
188     num_alloc = st->num + n;
189     if (num_alloc < min_nodes)
190         num_alloc = min_nodes;
191 
192     /* If |st->data| allocation was postponed */
193     if (st->data == NULL) {
194         /*
195          * At this point, |st->num_alloc| and |st->num| are 0;
196          * so |num_alloc| value is |n| or |min_nodes| if greater than |n|.
197          */
198         if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) {
199             ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
200             return 0;
201         }
202         st->num_alloc = num_alloc;
203         return 1;
204     }
205 
206     if (!exact) {
207         if (num_alloc <= st->num_alloc)
208             return 1;
209         num_alloc = compute_growth(num_alloc, st->num_alloc);
210         if (num_alloc == 0)
211             return 0;
212     } else if (num_alloc == st->num_alloc) {
213         return 1;
214     }
215 
216     tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc);
217     if (tmpdata == NULL)
218         return 0;
219 
220     st->data = tmpdata;
221     st->num_alloc = num_alloc;
222     return 1;
223 }
224 
OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c,int n)225 OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
226 {
227     OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK));
228 
229     if (st == NULL)
230         return NULL;
231 
232     st->comp = c;
233 
234     if (n <= 0)
235         return st;
236 
237     if (!sk_reserve(st, n, 1)) {
238         OPENSSL_sk_free(st);
239         return NULL;
240     }
241 
242     return st;
243 }
244 
OPENSSL_sk_reserve(OPENSSL_STACK * st,int n)245 int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
246 {
247     if (st == NULL)
248         return 0;
249 
250     if (n < 0)
251         return 1;
252     return sk_reserve(st, n, 1);
253 }
254 
OPENSSL_sk_insert(OPENSSL_STACK * st,const void * data,int loc)255 int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
256 {
257     if (st == NULL || st->num == max_nodes)
258         return 0;
259 
260     if (!sk_reserve(st, 1, 0))
261         return 0;
262 
263     if ((loc >= st->num) || (loc < 0)) {
264         st->data[st->num] = data;
265     } else {
266         memmove(&st->data[loc + 1], &st->data[loc],
267                 sizeof(st->data[0]) * (st->num - loc));
268         st->data[loc] = data;
269     }
270     st->num++;
271     st->sorted = 0;
272     return st->num;
273 }
274 
internal_delete(OPENSSL_STACK * st,int loc)275 static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc)
276 {
277     const void *ret = st->data[loc];
278 
279     if (loc != st->num - 1)
280          memmove(&st->data[loc], &st->data[loc + 1],
281                  sizeof(st->data[0]) * (st->num - loc - 1));
282     st->num--;
283 
284     return (void *)ret;
285 }
286 
OPENSSL_sk_delete_ptr(OPENSSL_STACK * st,const void * p)287 void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
288 {
289     int i;
290 
291     for (i = 0; i < st->num; i++)
292         if (st->data[i] == p)
293             return internal_delete(st, i);
294     return NULL;
295 }
296 
OPENSSL_sk_delete(OPENSSL_STACK * st,int loc)297 void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
298 {
299     if (st == NULL || loc < 0 || loc >= st->num)
300         return NULL;
301 
302     return internal_delete(st, loc);
303 }
304 
internal_find(OPENSSL_STACK * st,const void * data,int ret_val_options,int * pnum)305 static int internal_find(OPENSSL_STACK *st, const void *data,
306                          int ret_val_options, int *pnum)
307 {
308     const void *r;
309     int i;
310 
311     if (st == NULL || st->num == 0)
312         return -1;
313 
314     if (st->comp == NULL) {
315         for (i = 0; i < st->num; i++)
316             if (st->data[i] == data) {
317                 if (pnum != NULL)
318                     *pnum = 1;
319                 return i;
320             }
321         if (pnum != NULL)
322             *pnum = 0;
323         return -1;
324     }
325 
326     if (!st->sorted) {
327         if (st->num > 1)
328             qsort(st->data, st->num, sizeof(void *), st->comp);
329         st->sorted = 1; /* empty or single-element stack is considered sorted */
330     }
331     if (data == NULL)
332         return -1;
333     if (pnum != NULL)
334         ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
335     r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
336                      ret_val_options);
337 
338     if (pnum != NULL) {
339         *pnum = 0;
340         if (r != NULL) {
341             const void **p = (const void **)r;
342 
343             while (p < st->data + st->num) {
344                 if (st->comp(&data, p) != 0)
345                     break;
346                 ++*pnum;
347                 ++p;
348             }
349         }
350     }
351 
352     return r == NULL ? -1 : (int)((const void **)r - st->data);
353 }
354 
OPENSSL_sk_find(OPENSSL_STACK * st,const void * data)355 int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
356 {
357     return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
358 }
359 
OPENSSL_sk_find_ex(OPENSSL_STACK * st,const void * data)360 int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
361 {
362     return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
363 }
364 
OPENSSL_sk_find_all(OPENSSL_STACK * st,const void * data,int * pnum)365 int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum)
366 {
367     return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
368 }
369 
OPENSSL_sk_push(OPENSSL_STACK * st,const void * data)370 int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
371 {
372     if (st == NULL)
373         return -1;
374     return OPENSSL_sk_insert(st, data, st->num);
375 }
376 
OPENSSL_sk_unshift(OPENSSL_STACK * st,const void * data)377 int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
378 {
379     return OPENSSL_sk_insert(st, data, 0);
380 }
381 
OPENSSL_sk_shift(OPENSSL_STACK * st)382 void *OPENSSL_sk_shift(OPENSSL_STACK *st)
383 {
384     if (st == NULL || st->num == 0)
385         return NULL;
386     return internal_delete(st, 0);
387 }
388 
OPENSSL_sk_pop(OPENSSL_STACK * st)389 void *OPENSSL_sk_pop(OPENSSL_STACK *st)
390 {
391     if (st == NULL || st->num == 0)
392         return NULL;
393     return internal_delete(st, st->num - 1);
394 }
395 
OPENSSL_sk_zero(OPENSSL_STACK * st)396 void OPENSSL_sk_zero(OPENSSL_STACK *st)
397 {
398     if (st == NULL || st->num == 0)
399         return;
400     memset(st->data, 0, sizeof(*st->data) * st->num);
401     st->num = 0;
402 }
403 
OPENSSL_sk_pop_free(OPENSSL_STACK * st,OPENSSL_sk_freefunc func)404 void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
405 {
406     int i;
407 
408     if (st == NULL)
409         return;
410     for (i = 0; i < st->num; i++)
411         if (st->data[i] != NULL)
412             func((char *)st->data[i]);
413     OPENSSL_sk_free(st);
414 }
415 
OPENSSL_sk_free(OPENSSL_STACK * st)416 void OPENSSL_sk_free(OPENSSL_STACK *st)
417 {
418     if (st == NULL)
419         return;
420     OPENSSL_free(st->data);
421     OPENSSL_free(st);
422 }
423 
OPENSSL_sk_num(const OPENSSL_STACK * st)424 int OPENSSL_sk_num(const OPENSSL_STACK *st)
425 {
426     return st == NULL ? -1 : st->num;
427 }
428 
OPENSSL_sk_value(const OPENSSL_STACK * st,int i)429 void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
430 {
431     if (st == NULL || i < 0 || i >= st->num)
432         return NULL;
433     return (void *)st->data[i];
434 }
435 
OPENSSL_sk_set(OPENSSL_STACK * st,int i,const void * data)436 void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
437 {
438     if (st == NULL || i < 0 || i >= st->num)
439         return NULL;
440     st->data[i] = data;
441     st->sorted = 0;
442     return (void *)st->data[i];
443 }
444 
OPENSSL_sk_sort(OPENSSL_STACK * st)445 void OPENSSL_sk_sort(OPENSSL_STACK *st)
446 {
447     if (st != NULL && !st->sorted && st->comp != NULL) {
448         if (st->num > 1)
449             qsort(st->data, st->num, sizeof(void *), st->comp);
450         st->sorted = 1; /* empty or single-element stack is considered sorted */
451     }
452 }
453 
OPENSSL_sk_is_sorted(const OPENSSL_STACK * st)454 int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
455 {
456     return st == NULL ? 1 : st->sorted;
457 }
458