|
1 |
| -/* $OpenBSD: biotest.c,v 1.11 2022/12/08 11:32:27 tb Exp $ */ |
| 1 | +/* $OpenBSD: biotest.c,v 1.12 2022/12/08 12:27:03 tb Exp $ */ |
2 | 2 | /*
|
3 | 3 | * Copyright (c) 2014, 2022 Joel Sing <jsing@openbsd.org>
|
4 | 4 | * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
|
@@ -599,41 +599,43 @@ do_bio_chain_pop_test(void)
|
599 | 599 | }
|
600 | 600 |
|
601 | 601 | /*
|
602 |
| - * Link two linear chains of BIOs, A[], B[] of length N_CHAIN_BIOS together |
| 602 | + * Link two linear chains of BIOs, A[] and B[], of length N_CHAIN_BIOS together |
603 | 603 | * using either BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]).
|
604 | 604 | *
|
605 | 605 | * BIO_push() first walks the chain A[] to its end and then appends the tail
|
606 | 606 | * of chain B[] starting at B[j]. If j > 0, we get two chains
|
607 | 607 | *
|
608 | 608 | * A[0] -- ... -- A[N_CHAIN_BIOS - 1] -- B[j] -- ... -- B[N_CHAIN_BIOS - 1]
|
609 |
| - * |
| 609 | + * `- link created by BIO_push() |
610 | 610 | * B[0] -- ... -- B[j-1]
|
611 |
| - * --- oldhead -->| |
| 611 | + * |<-- oldhead -->| |
612 | 612 | *
|
613 | 613 | * of lengths N_CHAIN_BIOS + N_CHAIN_BIOS - j and j, respectively.
|
614 | 614 | * If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is
|
615 | 615 | * that the outcome of BIO_push(A[i], B[j]) apart from the return value is
|
616 | 616 | * independent of i.
|
617 | 617 | *
|
618 |
| - * Prior to bio_lib.c r1.41, BIO_push() would keep * BIO_next(B[j-1]) == B[j] |
619 |
| - * for 0 < j < N_CHAIN_BIOS, and at the same time for all j the inconsistent |
620 |
| - * BIO_prev(B[j]) == A[N_CHAIN_BIOS - 1]. |
| 618 | + * Prior to bio_lib.c r1.41, BIO_push(A[i], B[j]) would fail to dissociate the |
| 619 | + * two chains and leave B[j] with two parents for 0 < j < N_CHAIN_BIOS. |
| 620 | + * B[j]->prev_bio would point at A[N_CHAIN_BIOS - 1], while both B[j - 1] and |
| 621 | + * A[N_CHAIN_BIOS - 1] would point at B[j]. In particular, BIO_free_all(A[0]) |
| 622 | + * followed by BIO_free_all(B[0]) results in a double free of B[j]. |
621 | 623 | *
|
622 | 624 | * The result for BIO_set_next() is different: three chains are created.
|
623 | 625 | *
|
624 | 626 | * |--- oldtail -->
|
625 | 627 | * ... -- A[i-1] -- A[i] -- A[i+1] -- ...
|
626 | 628 | * \
|
627 |
| - * \ new link created by BIO_set_next() |
| 629 | + * \ link created by BIO_set_next() |
628 | 630 | * --- oldhead -->| \
|
629 | 631 | * ... -- B[j-1] -- B[j] -- B[j+1] -- ...
|
630 | 632 | *
|
631 | 633 | * After creating a new link, the new chain has length i + 1 + N_CHAIN_BIOS - j,
|
632 | 634 | * oldtail has length N_CHAIN_BIOS - i - 1 and oldhead has length j.
|
633 | 635 | *
|
634 |
| - * Prior to bio_lib.c r1.40, BIO_set_next() results in BIO_next(B[j-1]) == B[j], |
635 |
| - * B[j-1] == BIO_prev(B[j]), A[i] == BIO_prev(A[i+1]) and, in addition, |
636 |
| - * BIO_next(A[i]) == B[j], thus leaving A[] and B[] in an inconsistent state. |
| 636 | + * Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) results in both A[i] and |
| 637 | + * B[j - 1] pointing at B[j] while B[j] points back at A[i]. The result is |
| 638 | + * again double frees. |
637 | 639 | *
|
638 | 640 | * XXX: Should check that the callback is called on BIO_push() as expected.
|
639 | 641 | */
|
|
0 commit comments