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
3
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4
4
*
23
23
24
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
34
static BIO *
29
35
BIO_prev (BIO * bio )
@@ -34,37 +40,73 @@ BIO_prev(BIO *bio)
34
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
84
static int
38
85
bio_chain_pop_test (void )
39
86
{
40
- BIO * bio [N_CHAIN_BIOS ];
87
+ BIO * bio [CHAIN_POP_LEN ];
41
88
BIO * prev , * next ;
42
89
size_t i , j ;
43
90
int failed = 1 ;
44
91
45
- for (i = 0 ; i < N_CHAIN_BIOS ; i ++ ) {
92
+ for (i = 0 ; i < nitems ( bio ) ; i ++ ) {
46
93
memset (bio , 0 , sizeof (bio ));
47
94
prev = NULL ;
48
95
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 ;
56
98
57
99
/* Check that the doubly-linked list was set up as expected. */
58
100
if (BIO_prev (bio [0 ]) != NULL ) {
59
101
fprintf (stderr ,
60
102
"i = %zu: first BIO has predecessor\n" , i );
61
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
106
fprintf (stderr , "i = %zu: last BIO has successor\n" , i );
65
107
goto err ;
66
108
}
67
- for (j = 0 ; j < N_CHAIN_BIOS ; j ++ ) {
109
+ for (j = 0 ; j < nitems ( bio ) ; j ++ ) {
68
110
if (j > 0 ) {
69
111
if (BIO_prev (bio [j ]) != bio [j - 1 ]) {
70
112
fprintf (stderr , "i = %zu: "
@@ -73,7 +115,7 @@ bio_chain_pop_test(void)
73
115
goto err ;
74
116
}
75
117
}
76
- if (j < N_CHAIN_BIOS - 1 ) {
118
+ if (j < nitems ( bio ) - 1 ) {
77
119
if (BIO_next (bio [j ]) != bio [j + 1 ]) {
78
120
fprintf (stderr , "i = %zu: "
79
121
"BIO_next(bio[%zu]) != bio[%zu]\n" ,
@@ -92,7 +134,7 @@ bio_chain_pop_test(void)
92
134
goto err ;
93
135
}
94
136
95
- if (i < N_CHAIN_BIOS - 1 ) {
137
+ if (i < nitems ( bio ) - 1 ) {
96
138
if (next != bio [i + 1 ]) {
97
139
fprintf (stderr , "BIO_pop(bio[%zu]) did not "
98
140
"return bio[%zu]\n" , i , i + 1 );
@@ -118,7 +160,7 @@ bio_chain_pop_test(void)
118
160
j = 1 ;
119
161
}
120
162
121
- for (; j < N_CHAIN_BIOS ; j ++ ) {
163
+ for (; j < nitems ( bio ) ; j ++ ) {
122
164
if (j == i )
123
165
continue ;
124
166
if (BIO_next (prev ) != bio [j ]) {
@@ -139,16 +181,13 @@ bio_chain_pop_test(void)
139
181
goto err ;
140
182
}
141
183
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 ));
145
185
}
146
186
147
187
failed = 0 ;
148
188
149
189
err :
150
- for (i = 0 ; i < N_CHAIN_BIOS ; i ++ )
151
- BIO_free (bio [i ]);
190
+ bio_chain_destroy (bio , nitems (bio ));
152
191
153
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
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]).
250
289
*
251
290
* BIO_push() first walks the chain A[] to its end and then appends the tail
252
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]
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()
256
295
* B[0] -- ... -- B[j-1]
257
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
299
* If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is
261
300
* that the outcome of BIO_push(A[i], B[j]) apart from the return value is
262
301
* independent of i.
263
302
*
264
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 .
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])
268
307
* followed by BIO_free_all(B[0]) results in a double free of B[j].
269
308
*
270
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
315
* --- oldhead -->| \
277
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,
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.
281
320
*
282
321
* Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) results in both A[i] and
283
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
329
link_chains_at (size_t i , size_t j , int use_bio_push )
291
330
{
292
331
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 ;
295
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
336
int failed = 1 ;
298
337
299
338
memset (A , 0 , sizeof (A ));
300
339
memset (B , 0 , sizeof (B ));
301
340
341
+ if (i > nitems (A ) || j > nitems (B ))
342
+ goto err ;
343
+
302
344
/* 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 ;
317
349
318
350
/*
319
351
* Set our expectations. ... it's complicated.
320
352
*/
321
353
322
354
new_start = A [0 ];
323
- new_end = B [N_CHAIN_BIOS - 1 ];
355
+ new_end = B [nitems ( B ) - 1 ];
324
356
325
357
oldhead_length = j ;
326
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
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
370
/* oldtail doesn't exist in the BIO_push() case. */
339
371
oldtail_start = NULL ;
340
372
oldtail_end = NULL ;
341
373
oldtail_length = 0 ;
342
374
} else {
343
- new_length = i + 1 + N_CHAIN_BIOS - j ;
375
+ new_length = i + 1 + nitems ( B ) - j ;
344
376
345
377
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 ;
348
380
}
349
381
350
382
/*
@@ -391,10 +423,8 @@ link_chains_at(size_t i, size_t j, int use_bio_push)
391
423
failed = 0 ;
392
424
393
425
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 ));
398
428
399
429
return failed ;
400
430
}
@@ -405,8 +435,8 @@ link_chains(int use_bio_push)
405
435
size_t i , j ;
406
436
int failure = 0 ;
407
437
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 ++ ) {
410
440
failure |= link_chains_at (i , j , use_bio_push );
411
441
}
412
442
}
0 commit comments