diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/regress/lib/libcrypto/bio/bio_chain.c | 148 |
1 files changed, 89 insertions, 59 deletions
diff --git a/src/regress/lib/libcrypto/bio/bio_chain.c b/src/regress/lib/libcrypto/bio/bio_chain.c index 1676a5f512..3453312e06 100644 --- a/src/regress/lib/libcrypto/bio/bio_chain.c +++ b/src/regress/lib/libcrypto/bio/bio_chain.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bio_chain.c,v 1.3 2022/12/08 18:12:39 tb Exp $ */ | 1 | /* $OpenBSD: bio_chain.c,v 1.4 2022/12/08 18:15:36 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> | 3 | * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> |
| 4 | * | 4 | * |
| @@ -23,7 +23,13 @@ | |||
| 23 | 23 | ||
| 24 | #include "bio_local.h" | 24 | #include "bio_local.h" |
| 25 | 25 | ||
| 26 | #define N_CHAIN_BIOS 5 | 26 | #ifndef nitems |
| 27 | #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #define CHAIN_POP_LEN 5 | ||
| 31 | #define LINK_CHAIN_A_LEN 8 | ||
| 32 | #define LINK_CHAIN_B_LEN 5 | ||
| 27 | 33 | ||
| 28 | static BIO * | 34 | static BIO * |
| 29 | BIO_prev(BIO *bio) | 35 | BIO_prev(BIO *bio) |
| @@ -34,25 +40,61 @@ BIO_prev(BIO *bio) | |||
| 34 | return bio->prev_bio; | 40 | return bio->prev_bio; |
| 35 | } | 41 | } |
| 36 | 42 | ||
| 43 | static void bio_chain_destroy(BIO **, size_t); | ||
| 44 | |||
| 45 | static int | ||
| 46 | bio_chain_create(const BIO_METHOD *meth, BIO *chain[], size_t len) | ||
| 47 | { | ||
| 48 | BIO *prev; | ||
| 49 | size_t i; | ||
| 50 | |||
| 51 | memset(chain, 0, len * sizeof(BIO *)); | ||
| 52 | |||
| 53 | prev = NULL; | ||
| 54 | for (i = 0; i < len; i++) { | ||
| 55 | if ((chain[i] = BIO_new(meth)) == NULL) { | ||
| 56 | fprintf(stderr, "BIO_new failed\n"); | ||
| 57 | goto err; | ||
| 58 | } | ||
| 59 | if ((prev = BIO_push(prev, chain[i])) == NULL) { | ||
| 60 | fprintf(stderr, "BIO_push failed\n"); | ||
| 61 | goto err; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | return 1; | ||
| 66 | |||
| 67 | err: | ||
| 68 | bio_chain_destroy(chain, len); | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static void | ||
| 74 | bio_chain_destroy(BIO *chain[], size_t len) | ||
| 75 | { | ||
| 76 | size_t i; | ||
| 77 | |||
| 78 | for (i = 0; i < len; i++) | ||
| 79 | BIO_free(chain[i]); | ||
| 80 | |||
| 81 | memset(chain, 0, len * sizeof(BIO *)); | ||
| 82 | } | ||
| 83 | |||
| 37 | static int | 84 | static int |
| 38 | bio_chain_pop_test(void) | 85 | bio_chain_pop_test(void) |
| 39 | { | 86 | { |
| 40 | BIO *bio[N_CHAIN_BIOS]; | 87 | BIO *bio[CHAIN_POP_LEN]; |
| 41 | BIO *prev, *next; | 88 | BIO *prev, *next; |
| 42 | size_t i, j; | 89 | size_t i, j; |
| 43 | int failed = 1; | 90 | int failed = 1; |
| 44 | 91 | ||
| 45 | for (i = 0; i < N_CHAIN_BIOS; i++) { | 92 | for (i = 0; i < nitems(bio); i++) { |
| 46 | memset(bio, 0, sizeof(bio)); | 93 | memset(bio, 0, sizeof(bio)); |
| 47 | prev = NULL; | 94 | prev = NULL; |
| 48 | 95 | ||
| 49 | /* Create a linear chain of BIOs. */ | 96 | if (!bio_chain_create(BIO_s_null(), bio, nitems(bio))) |
| 50 | for (j = 0; j < N_CHAIN_BIOS; j++) { | 97 | goto err; |
| 51 | if ((bio[j] = BIO_new(BIO_s_null())) == NULL) | ||
| 52 | errx(1, "BIO_new"); | ||
| 53 | if ((prev = BIO_push(prev, bio[j])) == NULL) | ||
| 54 | errx(1, "BIO_push"); | ||
| 55 | } | ||
| 56 | 98 | ||
| 57 | /* Check that the doubly-linked list was set up as expected. */ | 99 | /* Check that the doubly-linked list was set up as expected. */ |
| 58 | if (BIO_prev(bio[0]) != NULL) { | 100 | if (BIO_prev(bio[0]) != NULL) { |
| @@ -60,11 +102,11 @@ bio_chain_pop_test(void) | |||
| 60 | "i = %zu: first BIO has predecessor\n", i); | 102 | "i = %zu: first BIO has predecessor\n", i); |
| 61 | goto err; | 103 | goto err; |
| 62 | } | 104 | } |
| 63 | if (BIO_next(bio[N_CHAIN_BIOS - 1]) != NULL) { | 105 | if (BIO_next(bio[nitems(bio) - 1]) != NULL) { |
| 64 | fprintf(stderr, "i = %zu: last BIO has successor\n", i); | 106 | fprintf(stderr, "i = %zu: last BIO has successor\n", i); |
| 65 | goto err; | 107 | goto err; |
| 66 | } | 108 | } |
| 67 | for (j = 0; j < N_CHAIN_BIOS; j++) { | 109 | for (j = 0; j < nitems(bio); j++) { |
| 68 | if (j > 0) { | 110 | if (j > 0) { |
| 69 | if (BIO_prev(bio[j]) != bio[j - 1]) { | 111 | if (BIO_prev(bio[j]) != bio[j - 1]) { |
| 70 | fprintf(stderr, "i = %zu: " | 112 | fprintf(stderr, "i = %zu: " |
| @@ -73,7 +115,7 @@ bio_chain_pop_test(void) | |||
| 73 | goto err; | 115 | goto err; |
| 74 | } | 116 | } |
| 75 | } | 117 | } |
| 76 | if (j < N_CHAIN_BIOS - 1) { | 118 | if (j < nitems(bio) - 1) { |
| 77 | if (BIO_next(bio[j]) != bio[j + 1]) { | 119 | if (BIO_next(bio[j]) != bio[j + 1]) { |
| 78 | fprintf(stderr, "i = %zu: " | 120 | fprintf(stderr, "i = %zu: " |
| 79 | "BIO_next(bio[%zu]) != bio[%zu]\n", | 121 | "BIO_next(bio[%zu]) != bio[%zu]\n", |
| @@ -92,7 +134,7 @@ bio_chain_pop_test(void) | |||
| 92 | goto err; | 134 | goto err; |
| 93 | } | 135 | } |
| 94 | 136 | ||
| 95 | if (i < N_CHAIN_BIOS - 1) { | 137 | if (i < nitems(bio) - 1) { |
| 96 | if (next != bio[i + 1]) { | 138 | if (next != bio[i + 1]) { |
| 97 | fprintf(stderr, "BIO_pop(bio[%zu]) did not " | 139 | fprintf(stderr, "BIO_pop(bio[%zu]) did not " |
| 98 | "return bio[%zu]\n", i, i + 1); | 140 | "return bio[%zu]\n", i, i + 1); |
| @@ -118,7 +160,7 @@ bio_chain_pop_test(void) | |||
| 118 | j = 1; | 160 | j = 1; |
| 119 | } | 161 | } |
| 120 | 162 | ||
| 121 | for (; j < N_CHAIN_BIOS; j++) { | 163 | for (; j < nitems(bio); j++) { |
| 122 | if (j == i) | 164 | if (j == i) |
| 123 | continue; | 165 | continue; |
| 124 | if (BIO_next(prev) != bio[j]) { | 166 | if (BIO_next(prev) != bio[j]) { |
| @@ -139,16 +181,13 @@ bio_chain_pop_test(void) | |||
| 139 | goto err; | 181 | goto err; |
| 140 | } | 182 | } |
| 141 | 183 | ||
| 142 | for (j = 0; j < N_CHAIN_BIOS; j++) | 184 | bio_chain_destroy(bio, nitems(bio)); |
| 143 | BIO_free(bio[j]); | ||
| 144 | memset(bio, 0, sizeof(bio)); | ||
| 145 | } | 185 | } |
| 146 | 186 | ||
| 147 | failed = 0; | 187 | failed = 0; |
| 148 | 188 | ||
| 149 | err: | 189 | err: |
| 150 | for (i = 0; i < N_CHAIN_BIOS; i++) | 190 | bio_chain_destroy(bio, nitems(bio)); |
| 151 | BIO_free(bio[i]); | ||
| 152 | 191 | ||
| 153 | return failed; | 192 | return failed; |
| 154 | } | 193 | } |
| @@ -245,26 +284,26 @@ check_chain(BIO *start, BIO *end, size_t expected_length, | |||
| 245 | } | 284 | } |
| 246 | 285 | ||
| 247 | /* | 286 | /* |
| 248 | * Link two linear chains of BIOs, A[] and B[], of length N_CHAIN_BIOS together | 287 | * Link two linear chains of BIOs A[] and B[] together using either |
| 249 | * using either BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]). | 288 | * BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]). |
| 250 | * | 289 | * |
| 251 | * BIO_push() first walks the chain A[] to its end and then appends the tail | 290 | * BIO_push() first walks the chain A[] to its end and then appends the tail |
| 252 | * of chain B[] starting at B[j]. If j > 0, we get two chains | 291 | * of chain B[] starting at B[j]. If j > 0, we get two chains |
| 253 | * | 292 | * |
| 254 | * A[0] -- ... -- A[N_CHAIN_BIOS - 1] -- B[j] -- ... -- B[N_CHAIN_BIOS - 1] | 293 | * A[0] -- ... -- A[nitems(A) - 1] -- B[j] -- ... -- B[nitems(B) - 1] |
| 255 | * `- link created by BIO_push() | 294 | * `- link created by BIO_push() |
| 256 | * B[0] -- ... -- B[j-1] | 295 | * B[0] -- ... -- B[j-1] |
| 257 | * |<-- oldhead -->| | 296 | * |<-- oldhead -->| |
| 258 | * | 297 | * |
| 259 | * of lengths N_CHAIN_BIOS + N_CHAIN_BIOS - j and j, respectively. | 298 | * of lengths nitems(A) + nitems(B) - j and j, respectively. |
| 260 | * If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is | 299 | * If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is |
| 261 | * that the outcome of BIO_push(A[i], B[j]) apart from the return value is | 300 | * that the outcome of BIO_push(A[i], B[j]) apart from the return value is |
| 262 | * independent of i. | 301 | * independent of i. |
| 263 | * | 302 | * |
| 264 | * Prior to bio_lib.c r1.41, BIO_push(A[i], B[j]) would fail to dissociate the | 303 | * Prior to bio_lib.c r1.41, BIO_push(A[i], B[j]) would fail to dissociate the |
| 265 | * two chains and leave B[j] with two parents for 0 < j < N_CHAIN_BIOS. | 304 | * two chains and leave B[j] with two parents for 0 < j < nitems(B). |
| 266 | * B[j]->prev_bio would point at A[N_CHAIN_BIOS - 1], while both B[j - 1] and | 305 | * B[j]->prev_bio would point at A[nitems(A) - 1], while both B[j - 1] and |
| 267 | * A[N_CHAIN_BIOS - 1] would point at B[j]. In particular, BIO_free_all(A[0]) | 306 | * A[nitems(A) - 1] would point at B[j]. In particular, BIO_free_all(A[0]) |
| 268 | * followed by BIO_free_all(B[0]) results in a double free of B[j]. | 307 | * followed by BIO_free_all(B[0]) results in a double free of B[j]. |
| 269 | * | 308 | * |
| 270 | * The result for BIO_set_next() is different: three chains are created. | 309 | * The result for BIO_set_next() is different: three chains are created. |
| @@ -276,8 +315,8 @@ check_chain(BIO *start, BIO *end, size_t expected_length, | |||
| 276 | * --- oldhead -->| \ | 315 | * --- oldhead -->| \ |
| 277 | * ... -- B[j-1] -- B[j] -- B[j+1] -- ... | 316 | * ... -- B[j-1] -- B[j] -- B[j+1] -- ... |
| 278 | * | 317 | * |
| 279 | * After creating a new link, the new chain has length i + 1 + N_CHAIN_BIOS - j, | 318 | * After creating a new link, the new chain has length i + 1 + nitems(B) - j, |
| 280 | * oldtail has length N_CHAIN_BIOS - i - 1 and oldhead has length j. | 319 | * oldtail has length nitems(A) - i - 1 and oldhead has length j. |
| 281 | * | 320 | * |
| 282 | * Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) results in both A[i] and | 321 | * Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) results in both A[i] and |
| 283 | * B[j - 1] pointing at B[j] while B[j] points back at A[i]. The result is | 322 | * B[j - 1] pointing at B[j] while B[j] points back at A[i]. The result is |
| @@ -290,37 +329,30 @@ static int | |||
| 290 | link_chains_at(size_t i, size_t j, int use_bio_push) | 329 | link_chains_at(size_t i, size_t j, int use_bio_push) |
| 291 | { | 330 | { |
| 292 | const char *fn = use_bio_push ? "BIO_push" : "BIO_set_next"; | 331 | const char *fn = use_bio_push ? "BIO_push" : "BIO_set_next"; |
| 293 | BIO *A[N_CHAIN_BIOS], *B[N_CHAIN_BIOS]; | 332 | BIO *A[LINK_CHAIN_A_LEN], *B[LINK_CHAIN_B_LEN]; |
| 294 | BIO *new_start, *new_end, *prev; | 333 | BIO *new_start, *new_end; |
| 295 | BIO *oldhead_start, *oldhead_end, *oldtail_start, *oldtail_end; | 334 | BIO *oldhead_start, *oldhead_end, *oldtail_start, *oldtail_end; |
| 296 | size_t k, new_length, oldhead_length, oldtail_length; | 335 | size_t new_length, oldhead_length, oldtail_length; |
| 297 | int failed = 1; | 336 | int failed = 1; |
| 298 | 337 | ||
| 299 | memset(A, 0, sizeof(A)); | 338 | memset(A, 0, sizeof(A)); |
| 300 | memset(B, 0, sizeof(B)); | 339 | memset(B, 0, sizeof(B)); |
| 301 | 340 | ||
| 341 | if (i > nitems(A) || j > nitems(B)) | ||
| 342 | goto err; | ||
| 343 | |||
| 302 | /* Create two linear chains of BIOs. */ | 344 | /* Create two linear chains of BIOs. */ |
| 303 | prev = NULL; | 345 | if (!bio_chain_create(BIO_s_null(), A, nitems(A))) |
| 304 | for (k = 0; k < N_CHAIN_BIOS; k++) { | 346 | goto err; |
| 305 | if ((A[k] = BIO_new(BIO_s_null())) == NULL) | 347 | if (!bio_chain_create(BIO_s_null(), B, nitems(B))) |
| 306 | errx(1, "BIO_new"); | 348 | goto err; |
| 307 | if ((prev = BIO_push(prev, A[k])) == NULL) | ||
| 308 | errx(1, "BIO_push"); | ||
| 309 | } | ||
| 310 | prev = NULL; | ||
| 311 | for (k = 0; k < N_CHAIN_BIOS; k++) { | ||
| 312 | if ((B[k] = BIO_new(BIO_s_null())) == NULL) | ||
| 313 | errx(1, "BIO_new"); | ||
| 314 | if ((prev = BIO_push(prev, B[k])) == NULL) | ||
| 315 | errx(1, "BIO_push"); | ||
| 316 | } | ||
| 317 | 349 | ||
| 318 | /* | 350 | /* |
| 319 | * Set our expectations. ... it's complicated. | 351 | * Set our expectations. ... it's complicated. |
| 320 | */ | 352 | */ |
| 321 | 353 | ||
| 322 | new_start = A[0]; | 354 | new_start = A[0]; |
| 323 | new_end = B[N_CHAIN_BIOS - 1]; | 355 | new_end = B[nitems(B) - 1]; |
| 324 | 356 | ||
| 325 | oldhead_length = j; | 357 | oldhead_length = j; |
| 326 | oldhead_start = B[0]; | 358 | oldhead_start = B[0]; |
| @@ -333,18 +365,18 @@ link_chains_at(size_t i, size_t j, int use_bio_push) | |||
| 333 | } | 365 | } |
| 334 | 366 | ||
| 335 | if (use_bio_push) { | 367 | if (use_bio_push) { |
| 336 | new_length = N_CHAIN_BIOS + N_CHAIN_BIOS - j; | 368 | new_length = nitems(A) + nitems(B) - j; |
| 337 | 369 | ||
| 338 | /* oldtail doesn't exist in the BIO_push() case. */ | 370 | /* oldtail doesn't exist in the BIO_push() case. */ |
| 339 | oldtail_start = NULL; | 371 | oldtail_start = NULL; |
| 340 | oldtail_end = NULL; | 372 | oldtail_end = NULL; |
| 341 | oldtail_length = 0; | 373 | oldtail_length = 0; |
| 342 | } else { | 374 | } else { |
| 343 | new_length = i + 1 + N_CHAIN_BIOS - j; | 375 | new_length = i + 1 + nitems(B) - j; |
| 344 | 376 | ||
| 345 | oldtail_start = BIO_next(A[i]); | 377 | oldtail_start = BIO_next(A[i]); |
| 346 | oldtail_end = A[N_CHAIN_BIOS - 1]; | 378 | oldtail_end = A[nitems(A) - 1]; |
| 347 | oldtail_length = N_CHAIN_BIOS - i - 1; | 379 | oldtail_length = nitems(A) - i - 1; |
| 348 | } | 380 | } |
| 349 | 381 | ||
| 350 | /* | 382 | /* |
| @@ -391,10 +423,8 @@ link_chains_at(size_t i, size_t j, int use_bio_push) | |||
| 391 | failed = 0; | 423 | failed = 0; |
| 392 | 424 | ||
| 393 | err: | 425 | err: |
| 394 | for (i = 0; i < N_CHAIN_BIOS; i++) | 426 | bio_chain_destroy(A, nitems(A)); |
| 395 | BIO_free(A[i]); | 427 | bio_chain_destroy(B, nitems(B)); |
| 396 | for (i = 0; i < N_CHAIN_BIOS; i++) | ||
| 397 | BIO_free(B[i]); | ||
| 398 | 428 | ||
| 399 | return failed; | 429 | return failed; |
| 400 | } | 430 | } |
| @@ -405,8 +435,8 @@ link_chains(int use_bio_push) | |||
| 405 | size_t i, j; | 435 | size_t i, j; |
| 406 | int failure = 0; | 436 | int failure = 0; |
| 407 | 437 | ||
| 408 | for (i = 0; i < N_CHAIN_BIOS; i++) { | 438 | for (i = 0; i < LINK_CHAIN_A_LEN; i++) { |
| 409 | for (j = 0; j < N_CHAIN_BIOS; j++) { | 439 | for (j = 0; j < LINK_CHAIN_B_LEN; j++) { |
| 410 | failure |= link_chains_at(i, j, use_bio_push); | 440 | failure |= link_chains_at(i, j, use_bio_push); |
| 411 | } | 441 | } |
| 412 | } | 442 | } |
