diff options
author | tb <> | 2022-12-08 11:32:27 +0000 |
---|---|---|
committer | tb <> | 2022-12-08 11:32:27 +0000 |
commit | fcac0017bcd7a37bcb9dfd7c35dbf36dff59d64e (patch) | |
tree | 58d4aa14aa923d5ff191e620552ac1b31e29c190 /src | |
parent | 2a9849a4fa03ac30a7766bfc597d055a16a07e83 (diff) | |
download | openbsd-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.c | 368 |
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 | |||
641 | static int | ||
642 | do_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 | |||
934 | static int | ||
935 | do_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 | |||
949 | static int | ||
950 | do_bio_push_link_test(void) | ||
951 | { | ||
952 | int use_bio_push = 1; | ||
953 | |||
954 | return do_bio_link_chains(use_bio_push); | ||
955 | } | ||
956 | |||
957 | static int | ||
958 | do_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 | |||
601 | int | 965 | int |
602 | main(int argc, char **argv) | 966 | main(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 | } |