Fix some undefined behaviour in stack test
[openssl.git] / test / stack_test.c
1 /*
2  * Copyright 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 /* ====================================================================
11  * Copyright (c) 2017 Oracle and/or its affiliates.  All rights reserved.
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16
17 #include <openssl/opensslconf.h>
18 #include <openssl/safestack.h>
19 #include <openssl/err.h>
20 #include <openssl/crypto.h>
21
22 #include "e_os.h"
23 #include "test_main.h"
24 #include "testutil.h"
25
26 /* The macros below generate unused functions which error out one of the clang
27  * builds.  We disable this check here.
28  */
29 #ifdef __clang__
30 #pragma clang diagnostic ignored "-Wunused-function"
31 #endif
32
33 typedef struct {
34     int n;
35     char c;
36 } SS;
37
38 typedef union {
39     int n;
40     char c;
41 } SU;
42
43 DEFINE_SPECIAL_STACK_OF(sint, int)
44 DEFINE_SPECIAL_STACK_OF_CONST(uchar, unsigned char)
45 DEFINE_STACK_OF(SS)
46 DEFINE_STACK_OF_CONST(SU)
47
48 static int int_compare(const int *const *a, const int *const *b)
49 {
50     if (**a < **b)
51         return -1;
52     if (**a > **b)
53         return 1;
54     return 0;
55 }
56
57 static int test_int_stack(void)
58 {
59     static int v[] = { 1, 2, -4, 16, 999, 1, -173, 1, 9 };
60     static int notpresent = -1;
61     const int n = OSSL_NELEM(v);
62     static struct {
63         int value;
64         int unsorted;
65         int sorted;
66         int ex;
67     } finds[] = {
68         { 2,    1,  5,  5   },
69         { 9,    7,  6,  6   },
70         { -173, 5,  0,  0   },
71         { 999,  3,  8,  8   },
72         { 0,   -1, -1,  1   }
73     };
74     const int n_finds = OSSL_NELEM(finds);
75     static struct {
76         int value;
77         int ex;
78     } exfinds[] = {
79         { 3,    5   },
80         { 1000, 8   },
81         { 20,   8   },
82         { -999, 0   },
83         { -5,   0   },
84         { 8,    5   }
85     };
86     const int n_exfinds = OSSL_NELEM(exfinds);
87     STACK_OF(sint) *s = sk_sint_new_null();
88     int i;
89     int testresult = 0;
90
91     /* Check push and num */
92     for (i = 0; i < n; i++) {
93         if (sk_sint_num(s) != i) {
94             fprintf(stderr, "test int stack size %d\n", i);
95             goto end;
96         }
97         sk_sint_push(s, v + i);
98     }
99     if (sk_sint_num(s) != n) {
100         fprintf(stderr, "test int stack size %d\n", n);
101         goto end;
102     }
103
104     /* check the values */
105     for (i = 0; i < n; i++)
106         if (sk_sint_value(s, i) != v + i) {
107             fprintf(stderr, "test int value %d\n", i);
108             goto end;
109         }
110
111     /* find unsorted -- the pointers are compared */
112     for (i = 0; i < n_finds; i++) {
113         int *val = (finds[i].unsorted == -1) ? &notpresent
114                                              : v + finds[i].unsorted;
115
116         if (sk_sint_find(s, val) != finds[i].unsorted) {
117             fprintf(stderr, "test int unsorted find %d\n", i);
118             goto end;
119         }
120     }
121
122     /* find_ex unsorted */
123     for (i = 0; i < n_finds; i++) {
124         int *val = (finds[i].unsorted == -1) ? &notpresent
125                                              : v + finds[i].unsorted;
126
127         if (sk_sint_find_ex(s, val) != finds[i].unsorted) {
128             fprintf(stderr, "test int unsorted find_ex %d\n", i);
129             goto end;
130         }
131     }
132
133     /* sorting */
134     if (sk_sint_is_sorted(s)) {
135         fprintf(stderr, "test int unsorted\n");
136         goto end;
137     }
138     sk_sint_set_cmp_func(s, &int_compare);
139     sk_sint_sort(s);
140     if (!sk_sint_is_sorted(s)) {
141         fprintf(stderr, "test int sorted\n");
142         goto end;
143     }
144
145     /* find sorted -- the value is matched so we don't need to locate it */
146     for (i = 0; i < n_finds; i++)
147         if (sk_sint_find(s, &finds[i].value) != finds[i].sorted) {
148             fprintf(stderr, "test int sorted find %d\n", i);
149             goto end;
150         }
151
152     /* find_ex sorted */
153     for (i = 0; i < n_finds; i++)
154         if (sk_sint_find_ex(s, &finds[i].value) != finds[i].ex) {
155             fprintf(stderr, "test int sorted find_ex present %d\n", i);
156             goto end;
157         }
158     for (i = 0; i < n_exfinds; i++)
159         if (sk_sint_find_ex(s, &exfinds[i].value) != exfinds[i].ex) {
160             fprintf(stderr, "test int sorted find_ex absent %d\n", i);
161             goto end;
162         }
163
164     /* shift */
165     if (sk_sint_shift(s) != v + 6) {
166         fprintf(stderr, "test int shift\n");
167         goto end;
168     }
169
170     testresult = 1;
171 end:
172     sk_sint_free(s);
173     return testresult;
174 }
175
176 static int uchar_compare(const unsigned char *const *a,
177                          const unsigned char *const *b)
178 {
179     return **a - (signed int)**b;
180 }
181
182 static int test_uchar_stack(void)
183 {
184     static const unsigned char v[] = { 1, 3, 7, 5, 255, 0 };
185     const int n = OSSL_NELEM(v);
186     STACK_OF(uchar) *s = sk_uchar_new(&uchar_compare), *r = NULL;
187     int i;
188     int testresult = 0;
189
190     /* unshift and num */
191     for (i = 0; i < n; i++) {
192         if (sk_uchar_num(s) != i) {
193             fprintf(stderr, "test uchar stack size %d\n", i);
194             goto end;
195         }
196         sk_uchar_unshift(s, v + i);
197     }
198     if (sk_uchar_num(s) != n) {
199         fprintf(stderr, "test uchar stack size %d\n", n);
200         goto end;
201     }
202
203     /* dup */
204     r = sk_uchar_dup(s);
205     if (sk_uchar_num(r) != n) {
206         fprintf(stderr, "test uchar dup size %d\n", n);
207         goto end;
208     }
209     sk_uchar_sort(r);
210
211     /* pop */
212     for (i = 0; i < n; i++) 
213         if (sk_uchar_pop(s) != v + i) {
214             fprintf(stderr, "test uchar pop %d\n", i);
215             goto end;
216         }
217
218     /* free -- we rely on the debug malloc to detect leakage here */
219     sk_uchar_free(s);
220     s = NULL;
221
222     /* dup again */
223     if (sk_uchar_num(r) != n) {
224         fprintf(stderr, "test uchar dup size %d\n", n);
225         goto end;
226     }
227
228     /* zero */
229     sk_uchar_zero(r);
230     if (sk_uchar_num(r) != 0) {
231         fprintf(stderr, "test uchar zero %d\n", n);
232         goto end;
233     }
234
235     /* insert */
236     sk_uchar_insert(r, v, 0);
237     sk_uchar_insert(r, v + 2, -1);
238     sk_uchar_insert(r, v + 1, 1);
239     for (i = 0; i < 3; i++)
240         if (sk_uchar_value(r, i) != v + i) {
241             fprintf(stderr, "test uchar insert %d\n", i);
242             goto end;
243         }
244
245     /* delete */
246     if (sk_uchar_delete(r, 12) != NULL) {
247         fprintf(stderr, "test uchar delete missing %d\n", n);
248         goto end;
249     }
250     if (sk_uchar_delete(r, 1) != v + 1) {
251         fprintf(stderr, "test uchar delete middle %d\n", n);
252         goto end;
253     }
254
255     /* set */
256     sk_uchar_set(r, 1, v + 1);
257     for (i = 0; i < 2; i++)
258         if (sk_uchar_value(r, i) != v + i) {
259             fprintf(stderr, "test uchar set %d\n", i);
260             goto end;
261         }
262
263     testresult = 1;
264 end:
265     sk_uchar_free(r);
266     sk_uchar_free(s);
267     return testresult;
268 }
269
270 static SS *SS_copy(const SS *p)
271 {
272     SS *q = OPENSSL_malloc(sizeof(*q));
273
274     if (q != NULL)
275         memcpy(q, p, sizeof(*q));
276     return q;
277 }
278
279 static void SS_free(SS *p) {
280     OPENSSL_free(p);
281 }
282
283 static int test_SS_stack(void)
284 {
285     STACK_OF(SS) *s = sk_SS_new_null();
286     STACK_OF(SS) *r = NULL;
287     SS *v[10], *p;
288     const int n = OSSL_NELEM(v);
289     int i;
290     int testresult = 0;
291
292     /* allocate and push */
293     for (i = 0; i < n; i++) {
294         v[i] = OPENSSL_malloc(sizeof(*v[i]));
295
296         if (v[i] == NULL) {
297             fprintf(stderr, "test SS memory allocation failure\n");
298             goto end;
299         }
300         v[i]->n = i;
301         v[i]->c = 'A' + i;
302         if (sk_SS_num(s) != i) {
303             fprintf(stderr, "test SS stack size %d\n", i);
304             goto end;
305         }
306         sk_SS_push(s, v[i]);
307     }
308     if (sk_SS_num(s) != n) {
309         fprintf(stderr, "test SS size %d\n", n);
310         goto end;
311     }
312
313     /* deepcopy */
314     r = sk_SS_deep_copy(s, &SS_copy, &SS_free);
315     if (r == NULL) {
316         fprintf(stderr, "test SS deepcopy failure\n");
317         goto end;
318     }
319     for (i = 0; i < n; i++) {
320         p = sk_SS_value(r, i);
321         if (p == v[i]) {
322             fprintf(stderr, "test SS deepcopy non-copy %d\n", i);
323             goto end;
324         }
325         if (p->n != v[i]->n || p->c != v[i]->c) {
326             fprintf(stderr, "test SS deepcopy values %d\n", i);
327             goto end;
328         }
329     }
330
331     /* pop_free - we rely on the malloc debug to catch the leak */
332     sk_SS_pop_free(r, &SS_free);
333     r = NULL;
334
335     /* delete_ptr */
336     if ((p = sk_SS_delete_ptr(s, v[3])) == NULL) {
337         fprintf(stderr, "test SS delete ptr not found\n");
338         goto end;
339     }
340     SS_free(p);
341     if (sk_SS_num(s) != n-1) {
342         fprintf(stderr, "test SS delete ptr size\n");
343         goto end;
344     }
345     for (i = 0; i < n-1; i++)
346         if (sk_SS_value(s, i) != v[i<3 ? i : 1+i]) {
347             fprintf(stderr, "test SS delete ptr item %d\n", i);
348             goto end;
349         }
350
351     testresult = 1;
352 end:
353     sk_SS_pop_free(r, &SS_free);
354     sk_SS_pop_free(s, &SS_free);
355     return testresult;
356 }
357
358 static int test_SU_stack(void)
359 {
360     STACK_OF(SU) *s = sk_SU_new_null();
361     SU v[10];
362     const int n = OSSL_NELEM(v);
363     int i;
364     int testresult = 0;
365
366     /* allocate and push */
367     for (i = 0; i < n; i++) {
368         if ((i & 1) == 0)
369             v[i].n = i;
370         else
371             v[i].c = 'A' + i;
372         if (sk_SU_num(s) != i) {
373             fprintf(stderr, "test SU stack size %d\n", i);
374             goto end;
375         }
376         sk_SU_push(s, v + i);
377     }
378     if (sk_SU_num(s) != n) {
379         fprintf(stderr, "test SU size %d\n", n);
380         goto end;
381     }
382
383     /* check the pointers are correct */
384     for (i = 0; i < n; i++)
385         if (sk_SU_value(s, i) != v + i) {
386             fprintf(stderr, "test SU pointer check %d\n", i);
387             goto end;
388         }
389
390     testresult = 1;
391 end:
392     sk_SU_free(s);
393     return testresult;
394 }
395
396 void register_tests(void)
397 {
398     ADD_TEST(test_int_stack);
399     ADD_TEST(test_uchar_stack);
400     ADD_TEST(test_SS_stack);
401     ADD_TEST(test_SU_stack);
402 }