Skip to content

Commit 16815bb

Browse files
committed
add kani harnesses for PhysFrame's Step implementation
These harnesses check that PhysFrame behaves like PhysAddr with the steps scaled by the page size.
1 parent 4b229b8 commit 16815bb

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

src/structures/paging/frame.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,4 +655,117 @@ mod proofs {
655655
range.nth_back(m);
656656
assert_eq!(range.nth_back(n), range2.nth_back(sum));
657657
}
658+
659+
// This harness proves that steps_between will return the same value
660+
// returned by PhysAddr's Step implementation scaled by Size4KiB::Size.
661+
#[kani::proof]
662+
fn steps_between() {
663+
let start_raw: u64 = kani::any();
664+
let Ok(start) = PhysAddr::try_new(start_raw) else {
665+
return;
666+
};
667+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
668+
return;
669+
};
670+
671+
let start_end: u64 = kani::any();
672+
let Ok(end) = PhysAddr::try_new(start_end) else {
673+
return;
674+
};
675+
let Ok(end_frame) = PhysFrame::<Size4KiB>::from_start_address(end) else {
676+
return;
677+
};
678+
679+
let (addr_min, addr_max) = PhysAddr::steps_between(&start, &end);
680+
let (frame_min, frame_max) = PhysFrame::steps_between(&start_frame, &end_frame);
681+
assert_eq!(addr_min / (Size4KiB::SIZE as usize), frame_min);
682+
assert_eq!(
683+
addr_max.map(|max| max / (Size4KiB::SIZE as usize)),
684+
frame_max
685+
);
686+
}
687+
688+
// This harness proves that forward_checked will return the same value
689+
// returned by PhysAddr's forward_checked implementation if the count has
690+
// scaled by Size4KiB::Size.
691+
#[kani::proof]
692+
fn forward() {
693+
let start_raw: u64 = kani::any();
694+
let Ok(start) = PhysAddr::try_new(start_raw) else {
695+
return;
696+
};
697+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
698+
return;
699+
};
700+
701+
let count: usize = kani::any();
702+
let Some(scaled_count) = count.checked_mul(Size4KiB::SIZE as usize) else {
703+
return;
704+
};
705+
706+
let end_addr = PhysAddr::forward_checked(start, scaled_count);
707+
let end_frame = PhysFrame::forward_checked(start_frame, count);
708+
assert_eq!(end_addr, end_frame.map(PhysFrame::start_address));
709+
}
710+
711+
// This harness proves that forward_checked will always return `None` if
712+
// the count cannot be scaled by Size4KiB::SIZE.
713+
#[kani::proof]
714+
fn forward_limit() {
715+
let start_raw: u64 = kani::any();
716+
let Ok(start) = PhysAddr::try_new(start_raw) else {
717+
return;
718+
};
719+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
720+
return;
721+
};
722+
723+
let count: usize = kani::any();
724+
kani::assume(count.checked_mul(Size4KiB::SIZE as usize).is_none());
725+
726+
let end_frame = PhysFrame::forward_checked(start_frame, count);
727+
assert_eq!(end_frame, None);
728+
}
729+
730+
// This harness proves that backward_checked will return the same value
731+
// returned by PhysAddr's backward_checked implementation if the count has
732+
// scaled by Size4KiB::Size.
733+
#[kani::proof]
734+
fn backward() {
735+
let start_raw: u64 = kani::any();
736+
let Ok(start) = PhysAddr::try_new(start_raw) else {
737+
return;
738+
};
739+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
740+
return;
741+
};
742+
743+
let count: usize = kani::any();
744+
let Some(scaled_count) = count.checked_mul(Size4KiB::SIZE as usize) else {
745+
return;
746+
};
747+
748+
let end_addr = PhysAddr::backward_checked(start, scaled_count);
749+
let end_frame = PhysFrame::backward_checked(start_frame, count);
750+
assert_eq!(end_addr, end_frame.map(PhysFrame::start_address));
751+
}
752+
753+
// This harness proves that backward_checked will always return `None` if
754+
// the count cannot be scaled by Size4KiB::SIZE.
755+
#[kani::proof]
756+
fn backward_limit() {
757+
let start_raw: u64 = kani::any();
758+
let Ok(start) = PhysAddr::try_new(start_raw) else {
759+
return;
760+
};
761+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
762+
return;
763+
};
764+
765+
let count: usize = kani::any();
766+
kani::assume(count.checked_mul(Size4KiB::SIZE as usize).is_none());
767+
768+
let end_frame = PhysFrame::backward_checked(start_frame, count);
769+
assert_eq!(end_frame, None);
770+
}
658771
}

0 commit comments

Comments
 (0)