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 } 381