Add a reserve call to the stack data structure.
[openssl.git] / crypto / stack / stack.c
1 /*
2  * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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 <openssl/stack.h>
14 #include <openssl/objects.h>
15 #include <errno.h>
16 #include <openssl/e_os2.h>      /* For ossl_inline */
17
18 /*
19  * The initial number of nodes in the array.
20  */
21 static const int min_nodes = 4;
22 static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX
23                              ? (int)(SIZE_MAX / sizeof(void *))
24                              : INT_MAX;
25
26 struct stack_st {
27     int num;
28     const void **data;
29     int sorted;
30     int num_alloc;
31     OPENSSL_sk_compfunc comp;
32 };
33
34 OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
35 {
36     OPENSSL_sk_compfunc old = sk->comp;
37
38     if (sk->comp != c)
39         sk->sorted = 0;
40     sk->comp = c;
41
42     return old;
43 }
44
45 OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
46 {
47     OPENSSL_STACK *ret;
48
49     if (sk->num < 0)
50         return NULL;
51
52     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
53         return NULL;
54
55     /* direct structure assignment */
56     *ret = *sk;
57
58     if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)
59         goto err;
60     memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
61     return ret;
62  err:
63     OPENSSL_sk_free(ret);
64     return NULL;
65 }
66
67 OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
68                              OPENSSL_sk_copyfunc copy_func,
69                              OPENSSL_sk_freefunc free_func)
70 {
71     OPENSSL_STACK *ret;
72     int i;
73
74     if (sk->num < 0)
75         return NULL;
76
77     if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
78         return NULL;
79
80     /* direct structure assignment */
81     *ret = *sk;
82
83     ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
84     ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);
85     if (ret->data == NULL) {
86         OPENSSL_free(ret);
87         return NULL;
88     }
89
90     for (i = 0; i < ret->num; ++i) {
91         if (sk->data[i] == NULL)
92             continue;
93         if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
94             while (--i >= 0)
95                 if (ret->data[i] != NULL)
96                     free_func((void *)ret->data[i]);
97             OPENSSL_sk_free(ret);
98             return NULL;
99         }
100     }
101     return ret;
102 }
103
104 OPENSSL_STACK *OPENSSL_sk_new_null(void)
105 {
106     return OPENSSL_sk_new((OPENSSL_sk_compfunc)NULL);
107 }
108
109 OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
110 {
111     OPENSSL_STACK *ret;
112
113     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
114         goto err;
115     if ((ret->data = OPENSSL_zalloc(sizeof(*ret->data) * min_nodes)) == NULL)
116         goto err;
117     ret->comp = c;
118     ret->num_alloc = min_nodes;
119     return (ret);
120
121  err:
122     OPENSSL_free(ret);
123     return (NULL);
124 }
125
126 /*
127  * Calculate the array growth based on the target size.
128  *
129  * The growth faction is a rational number and is defined by a numerator
130  * and a denominator.  According to Andrew Koenig in his paper "Why Are
131  * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
132  * than the golden ratio (1.618...).
133  *
134  * We use 3/2 = 1.5 for simplicty of calculation and overflow checking.
135  * Another option 8/5 = 1.6 allows for slightly faster growth, although safe
136  * computation is more difficult.
137  *
138  * The limit to avoid overflow is spot on.  The modulo three correction term
139  * ensures that the limit is the largest number than can be expanded by the
140  * growth factor without exceeding the hard limit.
141  */
142 static ossl_inline int compute_growth(int target, int current)
143 {
144     const int limit = (max_nodes / 3) * 2 + (max_nodes % 3 ? 1 : 0);
145
146     while (current < target) {
147         /* Check to see if we're at the hard limit */
148         if (current >= max_nodes)
149             return 0;
150
151         /* Expand the size by a factor of 3/2 if it is within range */
152         current = current < limit ? current + current / 2 : max_nodes;
153     }
154     return current;
155 }
156
157 static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
158 {
159     const void **tmpdata;
160     int num_alloc;
161
162     /* Check to see the reservation isn't exceeding the hard limit */
163     if (n > max_nodes - st->num)
164         return 0;
165
166     /* Figure out the new size */
167     num_alloc = st->num + n;
168     if (num_alloc < min_nodes)
169         num_alloc = min_nodes;
170
171     if (!exact) {
172         if (num_alloc <= st->num_alloc)
173             return 1;
174         num_alloc = compute_growth(num_alloc, st->num_alloc);
175         if (num_alloc == 0)
176             return 0;
177     } else if (num_alloc == st->num_alloc) {
178         return 1;
179     }
180
181     tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc);
182     if (tmpdata == NULL)
183         return 0;
184
185     st->data = tmpdata;
186     st->num_alloc = num_alloc;
187     return 1;
188 }
189
190 int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
191 {
192     if (st == NULL || st->num < 0)
193         return 0;
194
195     if (n < 0)
196         return 1;
197     return sk_reserve(st, n, 1);
198 }
199
200 int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
201 {
202     if (st == NULL || st->num < 0 || st->num == max_nodes)
203         return 0;
204
205     if (!sk_reserve(st, 1, 0))
206         return 0;
207
208     if ((loc >= st->num) || (loc < 0)) {
209         st->data[st->num] = data;
210     } else {
211         memmove(&st->data[loc + 1], &st->data[loc],
212                 sizeof(st->data[0]) * (st->num - loc));
213         st->data[loc] = data;
214     }
215     st->num++;
216     st->sorted = 0;
217     return st->num;
218 }
219
220 void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
221 {
222     int i;
223
224     for (i = 0; i < st->num; i++)
225         if (st->data[i] == p)
226             return OPENSSL_sk_delete(st, i);
227     return NULL;
228 }
229
230 void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
231 {
232     const void *ret;
233
234     if (st == NULL || loc < 0 || loc >= st->num)
235         return NULL;
236
237     ret = st->data[loc];
238     if (loc != st->num - 1)
239          memmove(&st->data[loc], &st->data[loc + 1],
240                  sizeof(st->data[0]) * (st->num - loc - 1));
241     st->num--;
242     return (void *)ret;
243 }
244
245 static int internal_find(OPENSSL_STACK *st, const void *data,
246                          int ret_val_options)
247 {
248     const void *r;
249     int i;
250
251     if (st == NULL)
252         return -1;
253
254     if (st->comp == NULL) {
255         for (i = 0; i < st->num; i++)
256             if (st->data[i] == data)
257                 return (i);
258         return (-1);
259     }
260     OPENSSL_sk_sort(st);
261     if (data == NULL)
262         return (-1);
263     r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
264                         ret_val_options);
265     if (r == NULL)
266         return (-1);
267     return (int)((const void **)r - st->data);
268 }
269
270 int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
271 {
272     return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
273 }
274
275 int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
276 {
277     return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
278 }
279
280 int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
281 {
282     return (OPENSSL_sk_insert(st, data, st->num));
283 }
284
285 int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
286 {
287     return (OPENSSL_sk_insert(st, data, 0));
288 }
289
290 void *OPENSSL_sk_shift(OPENSSL_STACK *st)
291 {
292     if (st == NULL)
293         return (NULL);
294     if (st->num <= 0)
295         return (NULL);
296     return (OPENSSL_sk_delete(st, 0));
297 }
298
299 void *OPENSSL_sk_pop(OPENSSL_STACK *st)
300 {
301     if (st == NULL)
302         return (NULL);
303     if (st->num <= 0)
304         return (NULL);
305     return (OPENSSL_sk_delete(st, st->num - 1));
306 }
307
308 void OPENSSL_sk_zero(OPENSSL_STACK *st)
309 {
310     if (st == NULL)
311         return;
312     if (st->num <= 0)
313         return;
314     memset(st->data, 0, sizeof(*st->data) * st->num);
315     st->num = 0;
316 }
317
318 void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
319 {
320     int i;
321
322     if (st == NULL)
323         return;
324     for (i = 0; i < st->num; i++)
325         if (st->data[i] != NULL)
326             func((char *)st->data[i]);
327     OPENSSL_sk_free(st);
328 }
329
330 void OPENSSL_sk_free(OPENSSL_STACK *st)
331 {
332     if (st == NULL)
333         return;
334     OPENSSL_free(st->data);
335     OPENSSL_free(st);
336 }
337
338 int OPENSSL_sk_num(const OPENSSL_STACK *st)
339 {
340     if (st == NULL)
341         return -1;
342     return st->num;
343 }
344
345 void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
346 {
347     if (st == NULL || i < 0 || i >= st->num)
348         return NULL;
349     return (void *)st->data[i];
350 }
351
352 void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
353 {
354     if (st == NULL || i < 0 || i >= st->num)
355         return NULL;
356     st->data[i] = data;
357     return (void *)st->data[i];
358 }
359
360 void OPENSSL_sk_sort(OPENSSL_STACK *st)
361 {
362     if (st && !st->sorted && st->comp != NULL) {
363         qsort(st->data, st->num, sizeof(void *), st->comp);
364         st->sorted = 1;
365     }
366 }
367
368 int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
369 {
370     if (st == NULL)
371         return 1;
372     return st->sorted;
373 }