summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/regress/lib/libcrypto/bio/bio_chain.c148
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
28static BIO * 34static BIO *
29BIO_prev(BIO *bio) 35BIO_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
43static void bio_chain_destroy(BIO **, size_t);
44
45static int
46bio_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
73static void
74bio_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
37static int 84static int
38bio_chain_pop_test(void) 85bio_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
290link_chains_at(size_t i, size_t j, int use_bio_push) 329link_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 }