summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-12-08 11:32:27 +0000
committertb <>2022-12-08 11:32:27 +0000
commitfcac0017bcd7a37bcb9dfd7c35dbf36dff59d64e (patch)
tree58d4aa14aa923d5ff191e620552ac1b31e29c190 /src
parent2a9849a4fa03ac30a7766bfc597d055a16a07e83 (diff)
downloadopenbsd-fcac0017bcd7a37bcb9dfd7c35dbf36dff59d64e.tar.gz
openbsd-fcac0017bcd7a37bcb9dfd7c35dbf36dff59d64e.tar.bz2
openbsd-fcac0017bcd7a37bcb9dfd7c35dbf36dff59d64e.zip
Add BIO_push() and BIO_set_next() regress coverage
This tests for the behavior changes in bio_lib.c r1.40 and r1.41 and makes sure that BIO_push() and BIO_set_next() act on two chains in the expected and now documented way.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libcrypto/bio/biotest.c368
1 files changed, 367 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/bio/biotest.c b/src/regress/lib/libcrypto/bio/biotest.c
index 55daea78fc..7d56448bfa 100644
--- a/src/regress/lib/libcrypto/bio/biotest.c
+++ b/src/regress/lib/libcrypto/bio/biotest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: biotest.c,v 1.10 2022/12/03 09:53:47 tb Exp $ */ 1/* $OpenBSD: biotest.c,v 1.11 2022/12/08 11:32:27 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2014, 2022 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014, 2022 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -598,6 +598,370 @@ do_bio_chain_pop_test(void)
598 return failed; 598 return failed;
599} 599}
600 600
601/*
602 * Link two linear chains of BIOs, A[], B[] of length N_CHAIN_BIOS together
603 * using either BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]).
604 *
605 * BIO_push() first walks the chain A[] to its end and then appends the tail
606 * of chain B[] starting at B[j]. If j > 0, we get two chains
607 *
608 * A[0] -- ... -- A[N_CHAIN_BIOS - 1] -- B[j] -- ... -- B[N_CHAIN_BIOS - 1]
609 *
610 * B[0] -- ... -- B[j-1]
611 * --- oldhead -->|
612 *
613 * of lengths N_CHAIN_BIOS + N_CHAIN_BIOS - j and j, respectively.
614 * If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is
615 * that the outcome of BIO_push(A[i], B[j]) apart from the return value is
616 * independent of i.
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].
621 *
622 * The result for BIO_set_next() is different: three chains are created.
623 *
624 * |--- oldtail -->
625 * ... -- A[i-1] -- A[i] -- A[i+1] -- ...
626 * \
627 * \ new link created by BIO_set_next()
628 * --- oldhead -->| \
629 * ... -- B[j-1] -- B[j] -- B[j+1] -- ...
630 *
631 * After creating a new link, the new chain has length i + 1 + N_CHAIN_BIOS - j,
632 * oldtail has length N_CHAIN_BIOS - i - 1 and oldhead has length j.
633 *
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.
637 *
638 * XXX: Should check that the callback is called on BIO_push() as expected.
639 */
640
641static int
642do_bio_link_chains_at(size_t i, size_t j, int use_bio_push)
643{
644 BIO *A[N_CHAIN_BIOS], *B[N_CHAIN_BIOS];
645 BIO *oldhead_start, *oldhead_end, *oldtail_start, *oldtail_end;
646 BIO *prev, *next;
647 size_t k, length, new_chain_length, oldhead_length, oldtail_length;
648 int failed = 1;
649
650 memset(A, 0, sizeof(A));
651 memset(B, 0, sizeof(A));
652
653 /* Create two linear chains of BIOs. */
654 prev = NULL;
655 for (k = 0; k < N_CHAIN_BIOS; k++) {
656 if ((A[k] = BIO_new(BIO_s_null())) == NULL)
657 errx(1, "BIO_new");
658 if ((prev = BIO_push(prev, A[k])) == NULL)
659 errx(1, "BIO_push");
660 }
661 prev = NULL;
662 for (k = 0; k < N_CHAIN_BIOS; k++) {
663 if ((B[k] = BIO_new(BIO_s_null())) == NULL)
664 errx(1, "BIO_new");
665 if ((prev = BIO_push(prev, B[k])) == NULL)
666 errx(1, "BIO_push");
667 }
668
669 /*
670 * Set our expectations. ... it's complicated.
671 */
672
673 oldhead_length = j;
674 oldhead_start = B[0];
675 oldhead_end = BIO_prev(B[j]);
676
677 /*
678 * Adjust for edge case where we push B[0] or set next to B[0].
679 * The oldhead chain is then empty.
680 */
681
682 if (j == 0) {
683 if (oldhead_end != NULL) {
684 fprintf(stderr, "%s: oldhead(B) not empty at start\n",
685 __func__);
686 goto err;
687 }
688
689 oldhead_length = 0;
690 oldhead_start = NULL;
691 }
692
693 if (use_bio_push) {
694 new_chain_length = N_CHAIN_BIOS + N_CHAIN_BIOS - j;
695
696 /* oldtail doesn't exist in the BIO_push() case. */
697 oldtail_start = NULL;
698 oldtail_end = NULL;
699 oldtail_length = 0;
700 } else {
701 new_chain_length = i + 1 + N_CHAIN_BIOS - j;
702
703 oldtail_start = BIO_next(A[i]);
704 oldtail_end = A[N_CHAIN_BIOS - 1];
705 oldtail_length = N_CHAIN_BIOS - i - 1;
706
707 /*
708 * In case we push onto (or set next at) the end of A[],
709 * the oldtail chain is empty.
710 */
711 if (i == N_CHAIN_BIOS - 1) {
712 if (oldtail_start != NULL) {
713 fprintf(stderr,
714 "%s: oldtail(A) not empty at end\n",
715 __func__);
716 goto err;
717 }
718
719 oldtail_end = NULL;
720 oldtail_length = 0;
721 }
722 }
723
724 /*
725 * Now actually push or set next.
726 */
727
728 if (use_bio_push) {
729 if (BIO_push(A[i], B[j]) != A[i]) {
730 fprintf(stderr,
731 "%s: BIO_push(A[%zu], B[%zu]) != A[%zu]\n",
732 __func__, i, j, i);
733 goto err;
734 }
735 } else {
736 BIO_set_next(A[i], B[j]);
737 }
738
739 /*
740 * Walk the new chain starting at A[0] forward. Check that we reach
741 * B[N_CHAIN_BIOS - 1] and that the new chain's length is as expected.
742 */
743
744 next = A[0];
745 length = 0;
746 do {
747 prev = next;
748 next = BIO_next(prev);
749 length++;
750 } while (next != NULL);
751
752 if (prev != B[N_CHAIN_BIOS - 1]) {
753 fprintf(stderr,
754 "%s(%zu, %zu, %d): new chain doesn't end in end of B\n",
755 __func__, i, j, use_bio_push);
756 goto err;
757 }
758
759 if (length != new_chain_length) {
760 fprintf(stderr, "%s(%zu, %zu, %d) unexpected new chain length"
761 " (walking forward). want %zu, got %zu\n",
762 __func__, i, j, use_bio_push, new_chain_length, length);
763 goto err;
764 }
765
766 /*
767 * Walk the new chain ending in B[N_CHAIN_BIOS - 1] backward.
768 * Check that we reach A[0] and that its length is what we expect.
769 */
770
771 prev = B[N_CHAIN_BIOS - 1];
772 length = 0;
773 do {
774 next = prev;
775 prev = BIO_prev(next);
776 length++;
777 } while (prev != NULL);
778
779 if (next != A[0]) {
780 fprintf(stderr,
781 "%s(%zu, %zu, %d): new chain doesn't start at start of A\n",
782 __func__, i, j, use_bio_push);
783 goto err;
784 }
785
786 if (length != new_chain_length) {
787 fprintf(stderr, "%s(%zu, %zu, %d) unexpected new chain length"
788 " (walking backward). want %zu, got %zu\n",
789 __func__, i, j, use_bio_push, new_chain_length, length);
790 goto err;
791 }
792
793 if (oldhead_start != NULL) {
794
795 /*
796 * Walk the old head forward and check its length.
797 */
798
799 next = oldhead_start;
800 length = 0;
801 do {
802 prev = next;
803 next = BIO_next(prev);
804 length++;
805 } while (next != NULL);
806
807 if (prev != oldhead_end) {
808 fprintf(stderr,
809 "%s(%zu, %zu, %d): unexpected old head end\n",
810 __func__, i, j, use_bio_push);
811 goto err;
812 }
813
814 if (length != oldhead_length) {
815 fprintf(stderr,
816 "%s(%zu, %zu, %d) unexpected old head length"
817 " (walking forward). want %zu, got %zu\n",
818 __func__, i, j, use_bio_push,
819 oldhead_length, length);
820 goto err;
821 }
822
823 /*
824 * Walk the old head backward and check its length.
825 */
826
827 prev = oldhead_end;
828 length = 0;
829 do {
830 next = prev;
831 prev = BIO_prev(next);
832 length++;
833 } while (prev != NULL);
834
835 if (next != oldhead_start) {
836 fprintf(stderr,
837 "%s(%zu, %zu, %d): unexpected old head start\n",
838 __func__, i, j, use_bio_push);
839 goto err;
840 }
841
842 if (length != oldhead_length) {
843 fprintf(stderr,
844 "%s(%zu, %zu, %d) unexpected old head length"
845 " (walking backward). want %zu, got %zu\n",
846 __func__, i, j, use_bio_push,
847 oldhead_length, length);
848 goto err;
849 }
850 }
851
852 if (oldtail_start != NULL) {
853
854 /*
855 * Walk the old tail forward and check its length.
856 */
857
858 next = oldtail_start;
859 length = 0;
860 do {
861 prev = next;
862 next = BIO_next(prev);
863 length++;
864 } while (next != NULL);
865
866 if (prev != oldtail_end) {
867 fprintf(stderr,
868 "%s(%zu, %zu, %d): unexpected old tail end\n",
869 __func__, i, j, use_bio_push);
870 goto err;
871 }
872
873 if (length != oldtail_length) {
874 fprintf(stderr,
875 "%s(%zu, %zu, %d) unexpected old tail length"
876 " (walking forward). want %zu, got %zu\n",
877 __func__, i, j, use_bio_push,
878 oldtail_length, length);
879 goto err;
880 }
881
882 /*
883 * Walk the old tail backward and check its length.
884 */
885
886 prev = oldtail_end;
887 length = 0;
888 do {
889 next = prev;
890 prev = BIO_prev(next);
891 length++;
892 } while (prev != NULL);
893
894 if (next != oldtail_start) {
895 fprintf(stderr,
896 "%s(%zu, %zu, %d): unexpected old tail start\n",
897 __func__, i, j, use_bio_push);
898 goto err;
899 }
900
901 if (length != oldtail_length) {
902 fprintf(stderr,
903 "%s(%zu, %zu, %d) unexpected old tail length"
904 " (walking backward). want %zu, got %zu\n",
905 __func__, i, j, use_bio_push,
906 oldtail_length, length);
907 goto err;
908 }
909 }
910
911 /*
912 * All sanity checks passed. We can now free the our chains
913 * with the BIO API without risk of leaks or double frees.
914 */
915
916 BIO_free_all(A[0]);
917 BIO_free_all(oldhead_start);
918 BIO_free_all(oldtail_start);
919
920 memset(A, 0, sizeof(A));
921 memset(B, 0, sizeof(B));
922
923 failed = 0;
924
925 err:
926 for (i = 0; i < N_CHAIN_BIOS; i++)
927 BIO_free(A[i]);
928 for (i = 0; i < N_CHAIN_BIOS; i++)
929 BIO_free(B[i]);
930
931 return failed;
932}
933
934static int
935do_bio_link_chains(int use_bio_push)
936{
937 size_t i, j;
938 int failure = 0;
939
940 for (i = 0; i < N_CHAIN_BIOS; i++) {
941 for (j = 0; j < N_CHAIN_BIOS; j++) {
942 failure |= do_bio_link_chains_at(i, j, use_bio_push);
943 }
944 }
945
946 return failure;
947}
948
949static int
950do_bio_push_link_test(void)
951{
952 int use_bio_push = 1;
953
954 return do_bio_link_chains(use_bio_push);
955}
956
957static int
958do_bio_set_next_link_test(void)
959{
960 int use_bio_push = 0;
961
962 return do_bio_link_chains(use_bio_push);
963}
964
601int 965int
602main(int argc, char **argv) 966main(int argc, char **argv)
603{ 967{
@@ -607,6 +971,8 @@ main(int argc, char **argv)
607 ret |= do_bio_get_port_tests(); 971 ret |= do_bio_get_port_tests();
608 ret |= do_bio_mem_tests(); 972 ret |= do_bio_mem_tests();
609 ret |= do_bio_chain_pop_test(); 973 ret |= do_bio_chain_pop_test();
974 ret |= do_bio_push_link_test();
975 ret |= do_bio_set_next_link_test();
610 976
611 return (ret); 977 return (ret);
612} 978}