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