Skip to content

Commit 4c11e1e

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 e928d47 commit 4c11e1e

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

src/structures/paging/frame.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,121 @@ mod tests {
309309
assert_eq!(range_inclusive.len(), 51);
310310
}
311311
}
312+
313+
#[cfg(kani)]
314+
mod proofs {
315+
use super::*;
316+
317+
// This harness proves that steps_between will return the same value
318+
// returned by PhysAddr's Step implementation scaled by Size4KiB::Size.
319+
#[kani::proof]
320+
fn steps_between() {
321+
let start_raw: u64 = kani::any();
322+
let Ok(start) = PhysAddr::try_new(start_raw) else {
323+
return;
324+
};
325+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
326+
return;
327+
};
328+
329+
let start_end: u64 = kani::any();
330+
let Ok(end) = PhysAddr::try_new(start_end) else {
331+
return;
332+
};
333+
let Ok(end_frame) = PhysFrame::<Size4KiB>::from_start_address(end) else {
334+
return;
335+
};
336+
337+
let (addr_min, addr_max) = PhysAddr::steps_between(&start, &end);
338+
let (frame_min, frame_max) = PhysFrame::steps_between(&start_frame, &end_frame);
339+
assert_eq!(addr_min / (Size4KiB::SIZE as usize), frame_min);
340+
assert_eq!(
341+
addr_max.map(|max| max / (Size4KiB::SIZE as usize)),
342+
frame_max
343+
);
344+
}
345+
346+
// This harness proves that forward_checked will return the same value
347+
// returned by PhysAddr's forward_checked implementation if the count has
348+
// scaled by Size4KiB::Size.
349+
#[kani::proof]
350+
fn forward() {
351+
let start_raw: u64 = kani::any();
352+
let Ok(start) = PhysAddr::try_new(start_raw) else {
353+
return;
354+
};
355+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
356+
return;
357+
};
358+
359+
let count: usize = kani::any();
360+
let Some(scaled_count) = count.checked_mul(Size4KiB::SIZE as usize) else {
361+
return;
362+
};
363+
364+
let end_addr = PhysAddr::forward_checked(start, scaled_count);
365+
let end_frame = PhysFrame::forward_checked(start_frame, count);
366+
assert_eq!(end_addr, end_frame.map(PhysFrame::start_address));
367+
}
368+
369+
// This harness proves that forward_checked will always return `None` if
370+
// the count cannot be scaled by Size4KiB::SIZE.
371+
#[kani::proof]
372+
fn forward_limit() {
373+
let start_raw: u64 = kani::any();
374+
let Ok(start) = PhysAddr::try_new(start_raw) else {
375+
return;
376+
};
377+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
378+
return;
379+
};
380+
381+
let count: usize = kani::any();
382+
kani::assume(count.checked_mul(Size4KiB::SIZE as usize).is_none());
383+
384+
let end_frame = PhysFrame::forward_checked(start_frame, count);
385+
assert_eq!(end_frame, None);
386+
}
387+
388+
// This harness proves that backward_checked will return the same value
389+
// returned by PhysAddr's backward_checked implementation if the count has
390+
// scaled by Size4KiB::Size.
391+
#[kani::proof]
392+
fn backward() {
393+
let start_raw: u64 = kani::any();
394+
let Ok(start) = PhysAddr::try_new(start_raw) else {
395+
return;
396+
};
397+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
398+
return;
399+
};
400+
401+
let count: usize = kani::any();
402+
let Some(scaled_count) = count.checked_mul(Size4KiB::SIZE as usize) else {
403+
return;
404+
};
405+
406+
let end_addr = PhysAddr::backward_checked(start, scaled_count);
407+
let end_frame = PhysFrame::backward_checked(start_frame, count);
408+
assert_eq!(end_addr, end_frame.map(PhysFrame::start_address));
409+
}
410+
411+
// This harness proves that backward_checked will always return `None` if
412+
// the count cannot be scaled by Size4KiB::SIZE.
413+
#[kani::proof]
414+
fn backward_limit() {
415+
let start_raw: u64 = kani::any();
416+
let Ok(start) = PhysAddr::try_new(start_raw) else {
417+
return;
418+
};
419+
let Ok(start_frame) = PhysFrame::<Size4KiB>::from_start_address(start) else {
420+
return;
421+
};
422+
423+
let count: usize = kani::any();
424+
kani::assume(count.checked_mul(Size4KiB::SIZE as usize).is_none());
425+
426+
let end_frame = PhysFrame::backward_checked(start_frame, count);
427+
assert_eq!(end_frame, None);
428+
}
429+
}

0 commit comments

Comments
 (0)