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