@@ -690,8 +690,7 @@ mod verification {
690
690
// >= 1.
691
691
const MAX_DESC_LENGTH : usize = 4 ;
692
692
693
- fn create_iovecs ( mem : * mut u8 , size : usize ) -> ( IoVecVec , u32 ) {
694
- let nr_descs: usize = kani:: any_where ( |& n| n <= MAX_DESC_LENGTH ) ;
693
+ fn create_iovecs ( mem : * mut u8 , size : usize , nr_descs : usize ) -> ( IoVecVec , u32 ) {
695
694
let mut vecs: Vec < iovec > = Vec :: with_capacity ( nr_descs) ;
696
695
let mut len = 0u32 ;
697
696
for _ in 0 ..nr_descs {
@@ -711,18 +710,18 @@ mod verification {
711
710
( vecs, len)
712
711
}
713
712
714
- impl kani :: Arbitrary for IoVecBuffer {
715
- fn any ( ) -> Self {
713
+ impl IoVecBuffer {
714
+ fn any_of_length ( nr_descs : usize ) -> Self {
716
715
// We only read from `IoVecBuffer`, so create here a guest memory object, with arbitrary
717
716
// contents and size up to GUEST_MEMORY_SIZE.
718
717
let mut mem = ManuallyDrop :: new ( kani:: vec:: exact_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ) ;
719
- let ( vecs, len) = create_iovecs ( mem. as_mut_ptr ( ) , mem. len ( ) ) ;
718
+ let ( vecs, len) = create_iovecs ( mem. as_mut_ptr ( ) , mem. len ( ) , nr_descs ) ;
720
719
Self { vecs, len }
721
720
}
722
721
}
723
722
724
- impl kani :: Arbitrary for IoVecBufferMut {
725
- fn any ( ) -> Self {
723
+ impl IoVecBufferMut {
724
+ fn any_of_length ( nr_descs : usize ) -> Self {
726
725
// We only write into `IoVecBufferMut` objects, so we can simply create a guest memory
727
726
// object initialized to zeroes, trying to be nice to Kani.
728
727
let mem = unsafe {
@@ -732,7 +731,7 @@ mod verification {
732
731
) )
733
732
} ;
734
733
735
- let ( vecs, len) = create_iovecs ( mem, GUEST_MEMORY_SIZE ) ;
734
+ let ( vecs, len) = create_iovecs ( mem, GUEST_MEMORY_SIZE , nr_descs ) ;
736
735
Self { vecs, len }
737
736
}
738
737
}
@@ -777,58 +776,65 @@ mod verification {
777
776
#[ kani:: unwind( 5 ) ]
778
777
#[ kani:: solver( cadical) ]
779
778
fn verify_read_from_iovec ( ) {
780
- let iov: IoVecBuffer = kani:: any ( ) ;
781
-
782
- let mut buf = vec ! [ 0 ; GUEST_MEMORY_SIZE ] ;
783
- let offset: u32 = kani:: any ( ) ;
784
-
785
- // We can't really check the contents that the operation here writes into `buf`, because
786
- // our `IoVecBuffer` being completely arbitrary can contain overlapping memory regions, so
787
- // checking the data copied is not exactly trivial.
788
- //
789
- // What we can verify is the bytes that we read out from guest memory:
790
- // - `buf.len()`, if `offset + buf.len() < iov.len()`;
791
- // - `iov.len() - offset`, otherwise.
792
- // Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
793
- // provided that the logic inside read_volatile_at is correct, we should always get Ok(...)
794
- assert_eq ! (
795
- iov. read_volatile_at(
796
- & mut KaniBuffer ( & mut buf) ,
797
- offset as usize ,
798
- GUEST_MEMORY_SIZE
799
- )
800
- . unwrap( ) ,
801
- buf. len( ) . min( iov. len( ) . saturating_sub( offset) as usize )
802
- ) ;
779
+ for nr_descs in 0 ..MAX_DESC_LENGTH {
780
+ let iov = IoVecBuffer :: any_of_length ( nr_descs) ;
781
+
782
+ let mut buf = vec ! [ 0 ; GUEST_MEMORY_SIZE ] ;
783
+ let offset: u32 = kani:: any ( ) ;
784
+
785
+ // We can't really check the contents that the operation here writes into `buf`, because
786
+ // our `IoVecBuffer` being completely arbitrary can contain overlapping memory regions,
787
+ // so checking the data copied is not exactly trivial.
788
+ //
789
+ // What we can verify is the bytes that we read out from guest memory:
790
+ // - `buf.len()`, if `offset + buf.len() < iov.len()`;
791
+ // - `iov.len() - offset`, otherwise.
792
+ // Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
793
+ // provided that the logic inside read_volatile_at is correct, we should always get
794
+ // Ok(...)
795
+ assert_eq ! (
796
+ iov. read_volatile_at(
797
+ & mut KaniBuffer ( & mut buf) ,
798
+ offset as usize ,
799
+ GUEST_MEMORY_SIZE
800
+ )
801
+ . unwrap( ) ,
802
+ buf. len( ) . min( iov. len( ) . saturating_sub( offset) as usize )
803
+ ) ;
804
+ }
803
805
}
804
806
805
807
#[ kani:: proof]
806
808
#[ kani:: unwind( 5 ) ]
807
809
#[ kani:: solver( cadical) ]
808
810
fn verify_write_to_iovec ( ) {
809
- let mut iov_mut: IoVecBufferMut = kani:: any ( ) ;
810
-
811
- let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
812
- let offset: u32 = kani:: any ( ) ;
813
-
814
- // We can't really check the contents that the operation here writes into `IoVecBufferMut`,
815
- // because our `IoVecBufferMut` being completely arbitrary can contain overlapping memory
816
- // regions, so checking the data copied is not exactly trivial.
817
- //
818
- // What we can verify is the bytes that we write into guest memory:
819
- // - `buf.len()`, if `offset + buf.len() < iov.len()`;
820
- // - `iov.len() - offset`, otherwise.
821
- // Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
822
- // provided that the logic inside write_volatile_at is correct, we should always get Ok(...)
823
- assert_eq ! (
824
- iov_mut
825
- . write_volatile_at(
826
- & mut KaniBuffer ( & mut buf) ,
827
- offset as usize ,
828
- GUEST_MEMORY_SIZE
829
- )
830
- . unwrap( ) ,
831
- buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
832
- ) ;
811
+ for nr_descs in 0 ..MAX_DESC_LENGTH {
812
+ let mut iov_mut = IoVecBufferMut :: any_of_length ( nr_descs) ;
813
+
814
+ let mut buf = kani:: vec:: any_vec :: < u8 , GUEST_MEMORY_SIZE > ( ) ;
815
+ let offset: u32 = kani:: any ( ) ;
816
+
817
+ // We can't really check the contents that the operation here writes into
818
+ // `IoVecBufferMut`, because our `IoVecBufferMut` being completely arbitrary
819
+ // can contain overlapping memory regions, so checking the data copied is
820
+ // not exactly trivial.
821
+ //
822
+ // What we can verify is the bytes that we write into guest memory:
823
+ // - `buf.len()`, if `offset + buf.len() < iov.len()`;
824
+ // - `iov.len() - offset`, otherwise.
825
+ // Furthermore, we know our Read-/WriteVolatile implementation above is infallible, so
826
+ // provided that the logic inside write_volatile_at is correct, we should always get
827
+ // Ok(...)
828
+ assert_eq ! (
829
+ iov_mut
830
+ . write_volatile_at(
831
+ & mut KaniBuffer ( & mut buf) ,
832
+ offset as usize ,
833
+ GUEST_MEMORY_SIZE
834
+ )
835
+ . unwrap( ) ,
836
+ buf. len( ) . min( iov_mut. len( ) . saturating_sub( offset) as usize )
837
+ ) ;
838
+ }
833
839
}
834
840
}
0 commit comments