xref: /netbsd-src/crypto/external/bsd/openssl/dist/test/stack_test.c (revision b0d1725196a7921d003d2c66a14f186abda4176b)
113d40330Schristos /*
2*b0d17251Schristos  * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
313d40330Schristos  * Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
413d40330Schristos  *
5*b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
613d40330Schristos  * this file except in compliance with the License.  You can obtain a copy
713d40330Schristos  * in the file LICENSE in the source distribution or at
813d40330Schristos  * https://www.openssl.org/source/license.html
913d40330Schristos  */
1013d40330Schristos 
1113d40330Schristos #include <stdio.h>
1213d40330Schristos #include <string.h>
1313d40330Schristos 
1413d40330Schristos #include <openssl/opensslconf.h>
1513d40330Schristos #include <openssl/safestack.h>
1613d40330Schristos #include <openssl/err.h>
1713d40330Schristos #include <openssl/crypto.h>
1813d40330Schristos 
1913d40330Schristos #include "internal/nelem.h"
2013d40330Schristos #include "testutil.h"
2113d40330Schristos 
2213d40330Schristos /* The macros below generate unused functions which error out one of the clang
2313d40330Schristos  * builds.  We disable this check here.
2413d40330Schristos  */
2513d40330Schristos #ifdef __clang__
2613d40330Schristos #pragma clang diagnostic ignored "-Wunused-function"
2713d40330Schristos #endif
2813d40330Schristos 
2913d40330Schristos typedef struct {
3013d40330Schristos     int n;
3113d40330Schristos     char c;
3213d40330Schristos } SS;
3313d40330Schristos 
3413d40330Schristos typedef union {
3513d40330Schristos     int n;
3613d40330Schristos     char c;
3713d40330Schristos } SU;
3813d40330Schristos 
DEFINE_SPECIAL_STACK_OF(sint,int)3913d40330Schristos DEFINE_SPECIAL_STACK_OF(sint, int)
4013d40330Schristos DEFINE_SPECIAL_STACK_OF_CONST(uchar, unsigned char)
4113d40330Schristos DEFINE_STACK_OF(SS)
4213d40330Schristos DEFINE_STACK_OF_CONST(SU)
4313d40330Schristos 
4413d40330Schristos static int int_compare(const int *const *a, const int *const *b)
4513d40330Schristos {
4613d40330Schristos     if (**a < **b)
4713d40330Schristos         return -1;
4813d40330Schristos     if (**a > **b)
4913d40330Schristos         return 1;
5013d40330Schristos     return 0;
5113d40330Schristos }
5213d40330Schristos 
test_int_stack(int reserve)5313d40330Schristos static int test_int_stack(int reserve)
5413d40330Schristos {
5513d40330Schristos     static int v[] = { 1, 2, -4, 16, 999, 1, -173, 1, 9 };
5613d40330Schristos     static int notpresent = -1;
5713d40330Schristos     const int n = OSSL_NELEM(v);
5813d40330Schristos     static struct {
5913d40330Schristos         int value;
6013d40330Schristos         int unsorted;
6113d40330Schristos         int sorted;
6213d40330Schristos         int ex;
6313d40330Schristos     } finds[] = {
6413d40330Schristos         { 2,    1,  5,  5   },
6513d40330Schristos         { 9,    7,  6,  6   },
6613d40330Schristos         { -173, 5,  0,  0   },
6713d40330Schristos         { 999,  3,  8,  8   },
6813d40330Schristos         { 0,   -1, -1,  1   }
6913d40330Schristos     };
7013d40330Schristos     const int n_finds = OSSL_NELEM(finds);
7113d40330Schristos     static struct {
7213d40330Schristos         int value;
7313d40330Schristos         int ex;
7413d40330Schristos     } exfinds[] = {
7513d40330Schristos         { 3,    5   },
7613d40330Schristos         { 1000, 8   },
7713d40330Schristos         { 20,   8   },
7813d40330Schristos         { -999, 0   },
7913d40330Schristos         { -5,   0   },
8013d40330Schristos         { 8,    5   }
8113d40330Schristos     };
8213d40330Schristos     const int n_exfinds = OSSL_NELEM(exfinds);
8313d40330Schristos     STACK_OF(sint) *s = sk_sint_new_null();
8413d40330Schristos     int i;
8513d40330Schristos     int testresult = 0;
8613d40330Schristos 
8713d40330Schristos     if (!TEST_ptr(s)
8813d40330Schristos         || (reserve > 0 && !TEST_true(sk_sint_reserve(s, 5 * reserve))))
8913d40330Schristos         goto end;
9013d40330Schristos 
9113d40330Schristos     /* Check push and num */
9213d40330Schristos     for (i = 0; i < n; i++) {
9313d40330Schristos         if (!TEST_int_eq(sk_sint_num(s), i)) {
9413d40330Schristos             TEST_info("int stack size %d", i);
9513d40330Schristos             goto end;
9613d40330Schristos         }
9713d40330Schristos         sk_sint_push(s, v + i);
9813d40330Schristos     }
9913d40330Schristos     if (!TEST_int_eq(sk_sint_num(s), n))
10013d40330Schristos         goto end;
10113d40330Schristos 
10213d40330Schristos     /* check the values */
10313d40330Schristos     for (i = 0; i < n; i++)
10413d40330Schristos         if (!TEST_ptr_eq(sk_sint_value(s, i), v + i)) {
10513d40330Schristos             TEST_info("int value %d", i);
10613d40330Schristos             goto end;
10713d40330Schristos         }
10813d40330Schristos 
10913d40330Schristos     /* find unsorted -- the pointers are compared */
11013d40330Schristos     for (i = 0; i < n_finds; i++) {
11113d40330Schristos         int *val = (finds[i].unsorted == -1) ? &notpresent
11213d40330Schristos                                              : v + finds[i].unsorted;
11313d40330Schristos 
11413d40330Schristos         if (!TEST_int_eq(sk_sint_find(s, val), finds[i].unsorted)) {
11513d40330Schristos             TEST_info("int unsorted find %d", i);
11613d40330Schristos             goto end;
11713d40330Schristos         }
11813d40330Schristos     }
11913d40330Schristos 
12013d40330Schristos     /* find_ex unsorted */
12113d40330Schristos     for (i = 0; i < n_finds; i++) {
12213d40330Schristos         int *val = (finds[i].unsorted == -1) ? &notpresent
12313d40330Schristos                                              : v + finds[i].unsorted;
12413d40330Schristos 
12513d40330Schristos         if (!TEST_int_eq(sk_sint_find_ex(s, val), finds[i].unsorted)) {
12613d40330Schristos             TEST_info("int unsorted find_ex %d", i);
12713d40330Schristos             goto end;
12813d40330Schristos         }
12913d40330Schristos     }
13013d40330Schristos 
13113d40330Schristos     /* sorting */
13213d40330Schristos     if (!TEST_false(sk_sint_is_sorted(s)))
13313d40330Schristos         goto end;
134*b0d17251Schristos     (void)sk_sint_set_cmp_func(s, &int_compare);
13513d40330Schristos     sk_sint_sort(s);
13613d40330Schristos     if (!TEST_true(sk_sint_is_sorted(s)))
13713d40330Schristos         goto end;
13813d40330Schristos 
13913d40330Schristos     /* find sorted -- the value is matched so we don't need to locate it */
14013d40330Schristos     for (i = 0; i < n_finds; i++)
14113d40330Schristos         if (!TEST_int_eq(sk_sint_find(s, &finds[i].value), finds[i].sorted)) {
14213d40330Schristos             TEST_info("int sorted find %d", i);
14313d40330Schristos             goto end;
14413d40330Schristos         }
14513d40330Schristos 
14613d40330Schristos     /* find_ex sorted */
14713d40330Schristos     for (i = 0; i < n_finds; i++)
14813d40330Schristos         if (!TEST_int_eq(sk_sint_find_ex(s, &finds[i].value), finds[i].ex)) {
14913d40330Schristos             TEST_info("int sorted find_ex present %d", i);
15013d40330Schristos             goto end;
15113d40330Schristos         }
15213d40330Schristos     for (i = 0; i < n_exfinds; i++)
15313d40330Schristos         if (!TEST_int_eq(sk_sint_find_ex(s, &exfinds[i].value), exfinds[i].ex)){
15413d40330Schristos             TEST_info("int sorted find_ex absent %d", i);
15513d40330Schristos             goto end;
15613d40330Schristos         }
15713d40330Schristos 
15813d40330Schristos     /* shift */
15913d40330Schristos     if (!TEST_ptr_eq(sk_sint_shift(s), v + 6))
16013d40330Schristos         goto end;
16113d40330Schristos 
16213d40330Schristos     testresult = 1;
16313d40330Schristos end:
16413d40330Schristos     sk_sint_free(s);
16513d40330Schristos     return testresult;
16613d40330Schristos }
16713d40330Schristos 
uchar_compare(const unsigned char * const * a,const unsigned char * const * b)16813d40330Schristos static int uchar_compare(const unsigned char *const *a,
16913d40330Schristos                          const unsigned char *const *b)
17013d40330Schristos {
17113d40330Schristos     return **a - (signed int)**b;
17213d40330Schristos }
17313d40330Schristos 
test_uchar_stack(int reserve)17413d40330Schristos static int test_uchar_stack(int reserve)
17513d40330Schristos {
17613d40330Schristos     static const unsigned char v[] = { 1, 3, 7, 5, 255, 0 };
17713d40330Schristos     const int n = OSSL_NELEM(v);
17813d40330Schristos     STACK_OF(uchar) *s = sk_uchar_new(&uchar_compare), *r = NULL;
17913d40330Schristos     int i;
18013d40330Schristos     int testresult = 0;
18113d40330Schristos 
18213d40330Schristos     if (!TEST_ptr(s)
18313d40330Schristos         || (reserve > 0 && !TEST_true(sk_uchar_reserve(s, 5 * reserve))))
18413d40330Schristos         goto end;
18513d40330Schristos 
18613d40330Schristos     /* unshift and num */
18713d40330Schristos     for (i = 0; i < n; i++) {
18813d40330Schristos         if (!TEST_int_eq(sk_uchar_num(s), i)) {
18913d40330Schristos             TEST_info("uchar stack size %d", i);
19013d40330Schristos             goto end;
19113d40330Schristos         }
19213d40330Schristos         sk_uchar_unshift(s, v + i);
19313d40330Schristos     }
19413d40330Schristos     if (!TEST_int_eq(sk_uchar_num(s), n))
19513d40330Schristos         goto end;
19613d40330Schristos 
19713d40330Schristos     /* dup */
198*b0d17251Schristos     r = sk_uchar_dup(NULL);
199*b0d17251Schristos     if (sk_uchar_num(r) != 0)
200*b0d17251Schristos         goto end;
201*b0d17251Schristos     sk_uchar_free(r);
20213d40330Schristos     r = sk_uchar_dup(s);
20313d40330Schristos     if (!TEST_int_eq(sk_uchar_num(r), n))
20413d40330Schristos         goto end;
20513d40330Schristos     sk_uchar_sort(r);
20613d40330Schristos 
20713d40330Schristos     /* pop */
20813d40330Schristos     for (i = 0; i < n; i++)
20913d40330Schristos         if (!TEST_ptr_eq(sk_uchar_pop(s), v + i)) {
21013d40330Schristos             TEST_info("uchar pop %d", i);
21113d40330Schristos             goto end;
21213d40330Schristos         }
21313d40330Schristos 
21413d40330Schristos     /* free -- we rely on the debug malloc to detect leakage here */
21513d40330Schristos     sk_uchar_free(s);
21613d40330Schristos     s = NULL;
21713d40330Schristos 
21813d40330Schristos     /* dup again */
21913d40330Schristos     if (!TEST_int_eq(sk_uchar_num(r), n))
22013d40330Schristos         goto end;
22113d40330Schristos 
22213d40330Schristos     /* zero */
22313d40330Schristos     sk_uchar_zero(r);
22413d40330Schristos     if (!TEST_int_eq(sk_uchar_num(r), 0))
22513d40330Schristos         goto end;
22613d40330Schristos 
22713d40330Schristos     /* insert */
22813d40330Schristos     sk_uchar_insert(r, v, 0);
22913d40330Schristos     sk_uchar_insert(r, v + 2, -1);
23013d40330Schristos     sk_uchar_insert(r, v + 1, 1);
23113d40330Schristos     for (i = 0; i < 3; i++)
23213d40330Schristos         if (!TEST_ptr_eq(sk_uchar_value(r, i), v + i)) {
23313d40330Schristos             TEST_info("uchar insert %d", i);
23413d40330Schristos             goto end;
23513d40330Schristos         }
23613d40330Schristos 
23713d40330Schristos     /* delete */
23813d40330Schristos     if (!TEST_ptr_null(sk_uchar_delete(r, 12)))
23913d40330Schristos         goto end;
24013d40330Schristos     if (!TEST_ptr_eq(sk_uchar_delete(r, 1), v + 1))
24113d40330Schristos         goto end;
24213d40330Schristos 
24313d40330Schristos     /* set */
244*b0d17251Schristos     (void)sk_uchar_set(r, 1, v + 1);
24513d40330Schristos     for (i = 0; i < 2; i++)
24613d40330Schristos         if (!TEST_ptr_eq(sk_uchar_value(r, i), v + i)) {
24713d40330Schristos             TEST_info("uchar set %d", i);
24813d40330Schristos             goto end;
24913d40330Schristos         }
25013d40330Schristos 
25113d40330Schristos     testresult = 1;
25213d40330Schristos end:
25313d40330Schristos     sk_uchar_free(r);
25413d40330Schristos     sk_uchar_free(s);
25513d40330Schristos     return testresult;
25613d40330Schristos }
25713d40330Schristos 
SS_copy(const SS * p)25813d40330Schristos static SS *SS_copy(const SS *p)
25913d40330Schristos {
26013d40330Schristos     SS *q = OPENSSL_malloc(sizeof(*q));
26113d40330Schristos 
26213d40330Schristos     if (q != NULL)
26313d40330Schristos         memcpy(q, p, sizeof(*q));
26413d40330Schristos     return q;
26513d40330Schristos }
26613d40330Schristos 
SS_free(SS * p)26713d40330Schristos static void SS_free(SS *p) {
26813d40330Schristos     OPENSSL_free(p);
26913d40330Schristos }
27013d40330Schristos 
test_SS_stack(void)27113d40330Schristos static int test_SS_stack(void)
27213d40330Schristos {
27313d40330Schristos     STACK_OF(SS) *s = sk_SS_new_null();
27413d40330Schristos     STACK_OF(SS) *r = NULL;
27513d40330Schristos     SS *v[10], *p;
27613d40330Schristos     const int n = OSSL_NELEM(v);
27713d40330Schristos     int i;
27813d40330Schristos     int testresult = 0;
27913d40330Schristos 
28013d40330Schristos     /* allocate and push */
28113d40330Schristos     for (i = 0; i < n; i++) {
28213d40330Schristos         v[i] = OPENSSL_malloc(sizeof(*v[i]));
28313d40330Schristos 
28413d40330Schristos         if (!TEST_ptr(v[i]))
28513d40330Schristos             goto end;
28613d40330Schristos         v[i]->n = i;
28713d40330Schristos         v[i]->c = 'A' + i;
28813d40330Schristos         if (!TEST_int_eq(sk_SS_num(s), i)) {
28913d40330Schristos             TEST_info("SS stack size %d", i);
29013d40330Schristos             goto end;
29113d40330Schristos         }
29213d40330Schristos         sk_SS_push(s, v[i]);
29313d40330Schristos     }
29413d40330Schristos     if (!TEST_int_eq(sk_SS_num(s), n))
29513d40330Schristos         goto end;
29613d40330Schristos 
29713d40330Schristos     /* deepcopy */
298*b0d17251Schristos     r = sk_SS_deep_copy(NULL, &SS_copy, &SS_free);
299*b0d17251Schristos     if (sk_SS_num(r) != 0)
300*b0d17251Schristos         goto end;
301*b0d17251Schristos     sk_SS_free(r);
30213d40330Schristos     r = sk_SS_deep_copy(s, &SS_copy, &SS_free);
30313d40330Schristos     if (!TEST_ptr(r))
30413d40330Schristos         goto end;
30513d40330Schristos     for (i = 0; i < n; i++) {
30613d40330Schristos         p = sk_SS_value(r, i);
30713d40330Schristos         if (!TEST_ptr_ne(p, v[i])) {
30813d40330Schristos             TEST_info("SS deepcopy non-copy %d", i);
30913d40330Schristos             goto end;
31013d40330Schristos         }
31113d40330Schristos         if (!TEST_int_eq(p->n, v[i]->n)) {
31213d40330Schristos             TEST_info("test SS deepcopy int %d", i);
31313d40330Schristos             goto end;
31413d40330Schristos         }
31513d40330Schristos         if (!TEST_char_eq(p->c, v[i]->c)) {
31613d40330Schristos             TEST_info("SS deepcopy char %d", i);
31713d40330Schristos             goto end;
31813d40330Schristos         }
31913d40330Schristos     }
32013d40330Schristos 
32113d40330Schristos     /* pop_free - we rely on the malloc debug to catch the leak */
32213d40330Schristos     sk_SS_pop_free(r, &SS_free);
32313d40330Schristos     r = NULL;
32413d40330Schristos 
32513d40330Schristos     /* delete_ptr */
32613d40330Schristos     p = sk_SS_delete_ptr(s, v[3]);
32713d40330Schristos     if (!TEST_ptr(p))
32813d40330Schristos         goto end;
32913d40330Schristos     SS_free(p);
33013d40330Schristos     if (!TEST_int_eq(sk_SS_num(s), n - 1))
33113d40330Schristos         goto end;
33213d40330Schristos     for (i = 0; i < n-1; i++)
33313d40330Schristos         if (!TEST_ptr_eq(sk_SS_value(s, i), v[i<3 ? i : 1+i])) {
33413d40330Schristos             TEST_info("SS delete ptr item %d", i);
33513d40330Schristos             goto end;
33613d40330Schristos         }
33713d40330Schristos 
33813d40330Schristos     testresult = 1;
33913d40330Schristos end:
34013d40330Schristos     sk_SS_pop_free(r, &SS_free);
34113d40330Schristos     sk_SS_pop_free(s, &SS_free);
34213d40330Schristos     return testresult;
34313d40330Schristos }
34413d40330Schristos 
test_SU_stack(void)34513d40330Schristos static int test_SU_stack(void)
34613d40330Schristos {
34713d40330Schristos     STACK_OF(SU) *s = sk_SU_new_null();
34813d40330Schristos     SU v[10];
34913d40330Schristos     const int n = OSSL_NELEM(v);
35013d40330Schristos     int i;
35113d40330Schristos     int testresult = 0;
35213d40330Schristos 
35313d40330Schristos     /* allocate and push */
35413d40330Schristos     for (i = 0; i < n; i++) {
35513d40330Schristos         if ((i & 1) == 0)
35613d40330Schristos             v[i].n = i;
35713d40330Schristos         else
35813d40330Schristos             v[i].c = 'A' + i;
35913d40330Schristos         if (!TEST_int_eq(sk_SU_num(s), i)) {
36013d40330Schristos             TEST_info("SU stack size %d", i);
36113d40330Schristos             goto end;
36213d40330Schristos         }
36313d40330Schristos         sk_SU_push(s, v + i);
36413d40330Schristos     }
36513d40330Schristos     if (!TEST_int_eq(sk_SU_num(s), n))
36613d40330Schristos         goto end;
36713d40330Schristos 
36813d40330Schristos     /* check the pointers are correct */
36913d40330Schristos     for (i = 0; i < n; i++)
37013d40330Schristos         if (!TEST_ptr_eq(sk_SU_value(s, i),  v + i)) {
37113d40330Schristos             TEST_info("SU pointer check %d", i);
37213d40330Schristos             goto end;
37313d40330Schristos         }
37413d40330Schristos 
37513d40330Schristos     testresult = 1;
37613d40330Schristos end:
37713d40330Schristos     sk_SU_free(s);
37813d40330Schristos     return testresult;
37913d40330Schristos }
38013d40330Schristos 
setup_tests(void)38113d40330Schristos int setup_tests(void)
38213d40330Schristos {
38313d40330Schristos     ADD_ALL_TESTS(test_int_stack, 4);
38413d40330Schristos     ADD_ALL_TESTS(test_uchar_stack, 4);
38513d40330Schristos     ADD_TEST(test_SS_stack);
38613d40330Schristos     ADD_TEST(test_SU_stack);
38713d40330Schristos     return 1;
38813d40330Schristos }
389