Skip to content

Commit 5312697

Browse files
author
tb
committed
bio chain test: decouple lengths of test chains
Add helpers to create and destroy a linear chain of BIOs. Provide two defines for the two lengths of the test chains and make them distinct to rule out coincidences. As a bonus, the code becomes simpler.
1 parent b1b1dfd commit 5312697

File tree

1 file changed

+89
-59
lines changed

1 file changed

+89
-59
lines changed

src/regress/lib/libcrypto/bio/bio_chain.c

Lines changed: 89 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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 $ */
22
/*
33
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
44
*
@@ -23,7 +23,13 @@
2323

2424
#include "bio_local.h"
2525

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
2733

2834
static BIO *
2935
BIO_prev(BIO *bio)
@@ -34,37 +40,73 @@ BIO_prev(BIO *bio)
3440
return bio->prev_bio;
3541
}
3642

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+
3784
static int
3885
bio_chain_pop_test(void)
3986
{
40-
BIO *bio[N_CHAIN_BIOS];
87+
BIO *bio[CHAIN_POP_LEN];
4188
BIO *prev, *next;
4289
size_t i, j;
4390
int failed = 1;
4491

45-
for (i = 0; i < N_CHAIN_BIOS; i++) {
92+
for (i = 0; i < nitems(bio); i++) {
4693
memset(bio, 0, sizeof(bio));
4794
prev = NULL;
4895

49-
/* Create a linear chain of BIOs. */
50-
for (j = 0; j < N_CHAIN_BIOS; j++) {
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-
}
96+
if (!bio_chain_create(BIO_s_null(), bio, nitems(bio)))
97+
goto err;
5698

5799
/* Check that the doubly-linked list was set up as expected. */
58100
if (BIO_prev(bio[0]) != NULL) {
59101
fprintf(stderr,
60102
"i = %zu: first BIO has predecessor\n", i);
61103
goto err;
62104
}
63-
if (BIO_next(bio[N_CHAIN_BIOS - 1]) != NULL) {
105+
if (BIO_next(bio[nitems(bio) - 1]) != NULL) {
64106
fprintf(stderr, "i = %zu: last BIO has successor\n", i);
65107
goto err;
66108
}
67-
for (j = 0; j < N_CHAIN_BIOS; j++) {
109+
for (j = 0; j < nitems(bio); j++) {
68110
if (j > 0) {
69111
if (BIO_prev(bio[j]) != bio[j - 1]) {
70112
fprintf(stderr, "i = %zu: "
@@ -73,7 +115,7 @@ bio_chain_pop_test(void)
73115
goto err;
74116
}
75117
}
76-
if (j < N_CHAIN_BIOS - 1) {
118+
if (j < nitems(bio) - 1) {
77119
if (BIO_next(bio[j]) != bio[j + 1]) {
78120
fprintf(stderr, "i = %zu: "
79121
"BIO_next(bio[%zu]) != bio[%zu]\n",
@@ -92,7 +134,7 @@ bio_chain_pop_test(void)
92134
goto err;
93135
}
94136

95-
if (i < N_CHAIN_BIOS - 1) {
137+
if (i < nitems(bio) - 1) {
96138
if (next != bio[i + 1]) {
97139
fprintf(stderr, "BIO_pop(bio[%zu]) did not "
98140
"return bio[%zu]\n", i, i + 1);
@@ -118,7 +160,7 @@ bio_chain_pop_test(void)
118160
j = 1;
119161
}
120162

121-
for (; j < N_CHAIN_BIOS; j++) {
163+
for (; j < nitems(bio); j++) {
122164
if (j == i)
123165
continue;
124166
if (BIO_next(prev) != bio[j]) {
@@ -139,16 +181,13 @@ bio_chain_pop_test(void)
139181
goto err;
140182
}
141183

142-
for (j = 0; j < N_CHAIN_BIOS; j++)
143-
BIO_free(bio[j]);
144-
memset(bio, 0, sizeof(bio));
184+
bio_chain_destroy(bio, nitems(bio));
145185
}
146186

147187
failed = 0;
148188

149189
err:
150-
for (i = 0; i < N_CHAIN_BIOS; i++)
151-
BIO_free(bio[i]);
190+
bio_chain_destroy(bio, nitems(bio));
152191

153192
return failed;
154193
}
@@ -245,26 +284,26 @@ check_chain(BIO *start, BIO *end, size_t expected_length,
245284
}
246285

247286
/*
248-
* Link two linear chains of BIOs, A[] and B[], of length N_CHAIN_BIOS together
249-
* using either BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]).
287+
* Link two linear chains of BIOs A[] and B[] together using either
288+
* BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]).
250289
*
251290
* BIO_push() first walks the chain A[] to its end and then appends the tail
252291
* of chain B[] starting at B[j]. If j > 0, we get two chains
253292
*
254-
* A[0] -- ... -- A[N_CHAIN_BIOS - 1] -- B[j] -- ... -- B[N_CHAIN_BIOS - 1]
255-
* `- link created by BIO_push()
293+
* A[0] -- ... -- A[nitems(A) - 1] -- B[j] -- ... -- B[nitems(B) - 1]
294+
* `- link created by BIO_push()
256295
* B[0] -- ... -- B[j-1]
257296
* |<-- oldhead -->|
258297
*
259-
* of lengths N_CHAIN_BIOS + N_CHAIN_BIOS - j and j, respectively.
298+
* of lengths nitems(A) + nitems(B) - j and j, respectively.
260299
* If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is
261300
* that the outcome of BIO_push(A[i], B[j]) apart from the return value is
262301
* independent of i.
263302
*
264303
* 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.
266-
* B[j]->prev_bio would point at A[N_CHAIN_BIOS - 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])
304+
* two chains and leave B[j] with two parents for 0 < j < nitems(B).
305+
* B[j]->prev_bio would point at A[nitems(A) - 1], while both B[j - 1] and
306+
* A[nitems(A) - 1] would point at B[j]. In particular, BIO_free_all(A[0])
268307
* followed by BIO_free_all(B[0]) results in a double free of B[j].
269308
*
270309
* 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,
276315
* --- oldhead -->| \
277316
* ... -- B[j-1] -- B[j] -- B[j+1] -- ...
278317
*
279-
* After creating a new link, the new chain has length i + 1 + N_CHAIN_BIOS - j,
280-
* oldtail has length N_CHAIN_BIOS - i - 1 and oldhead has length j.
318+
* After creating a new link, the new chain has length i + 1 + nitems(B) - j,
319+
* oldtail has length nitems(A) - i - 1 and oldhead has length j.
281320
*
282321
* Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) results in both A[i] and
283322
* B[j - 1] pointing at B[j] while B[j] points back at A[i]. The result is
@@ -290,37 +329,30 @@ static int
290329
link_chains_at(size_t i, size_t j, int use_bio_push)
291330
{
292331
const char *fn = use_bio_push ? "BIO_push" : "BIO_set_next";
293-
BIO *A[N_CHAIN_BIOS], *B[N_CHAIN_BIOS];
294-
BIO *new_start, *new_end, *prev;
332+
BIO *A[LINK_CHAIN_A_LEN], *B[LINK_CHAIN_B_LEN];
333+
BIO *new_start, *new_end;
295334
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;
297336
int failed = 1;
298337

299338
memset(A, 0, sizeof(A));
300339
memset(B, 0, sizeof(B));
301340

341+
if (i > nitems(A) || j > nitems(B))
342+
goto err;
343+
302344
/* Create two linear chains of BIOs. */
303-
prev = NULL;
304-
for (k = 0; k < N_CHAIN_BIOS; k++) {
305-
if ((A[k] = BIO_new(BIO_s_null())) == NULL)
306-
errx(1, "BIO_new");
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-
}
345+
if (!bio_chain_create(BIO_s_null(), A, nitems(A)))
346+
goto err;
347+
if (!bio_chain_create(BIO_s_null(), B, nitems(B)))
348+
goto err;
317349

318350
/*
319351
* Set our expectations. ... it's complicated.
320352
*/
321353

322354
new_start = A[0];
323-
new_end = B[N_CHAIN_BIOS - 1];
355+
new_end = B[nitems(B) - 1];
324356

325357
oldhead_length = j;
326358
oldhead_start = B[0];
@@ -333,18 +365,18 @@ link_chains_at(size_t i, size_t j, int use_bio_push)
333365
}
334366

335367
if (use_bio_push) {
336-
new_length = N_CHAIN_BIOS + N_CHAIN_BIOS - j;
368+
new_length = nitems(A) + nitems(B) - j;
337369

338370
/* oldtail doesn't exist in the BIO_push() case. */
339371
oldtail_start = NULL;
340372
oldtail_end = NULL;
341373
oldtail_length = 0;
342374
} else {
343-
new_length = i + 1 + N_CHAIN_BIOS - j;
375+
new_length = i + 1 + nitems(B) - j;
344376

345377
oldtail_start = BIO_next(A[i]);
346-
oldtail_end = A[N_CHAIN_BIOS - 1];
347-
oldtail_length = N_CHAIN_BIOS - i - 1;
378+
oldtail_end = A[nitems(A) - 1];
379+
oldtail_length = nitems(A) - i - 1;
348380
}
349381

350382
/*
@@ -391,10 +423,8 @@ link_chains_at(size_t i, size_t j, int use_bio_push)
391423
failed = 0;
392424

393425
err:
394-
for (i = 0; i < N_CHAIN_BIOS; i++)
395-
BIO_free(A[i]);
396-
for (i = 0; i < N_CHAIN_BIOS; i++)
397-
BIO_free(B[i]);
426+
bio_chain_destroy(A, nitems(A));
427+
bio_chain_destroy(B, nitems(B));
398428

399429
return failed;
400430
}
@@ -405,8 +435,8 @@ link_chains(int use_bio_push)
405435
size_t i, j;
406436
int failure = 0;
407437

408-
for (i = 0; i < N_CHAIN_BIOS; i++) {
409-
for (j = 0; j < N_CHAIN_BIOS; j++) {
438+
for (i = 0; i < LINK_CHAIN_A_LEN; i++) {
439+
for (j = 0; j < LINK_CHAIN_B_LEN; j++) {
410440
failure |= link_chains_at(i, j, use_bio_push);
411441
}
412442
}

0 commit comments

Comments
 (0)