Verify safety of NonZero operations (Challenge 12)#544
Verify safety of NonZero operations (Challenge 12)#544jrey8343 wants to merge 4 commits intomodel-checking:mainfrom
Conversation
Add verification harnesses for all remaining NonZero functions: bit operations (count_ones, swap_bytes, reverse_bits, rotate_left, rotate_right), byte order (from_be, from_le, to_be, to_le), bitor (all 3 impls), checked/saturating arithmetic (checked_mul, saturating_mul, checked_add, saturating_add, checked_pow, saturating_pow), power of two (checked_next_power_of_two), midpoint, isqrt, signed operations (neg, abs, checked_abs, overflowing_abs, saturating_abs, wrapping_abs, unsigned_abs, checked_neg, overflowing_neg, wrapping_neg), and from_mut. Remove trivial loop_invariant(true) annotations from primitive checked_pow that caused CBMC assigns check interference with NonZero::new_unchecked verification. Total: 385 harnesses pass (376 new + 9 existing).
The 128-bit saturating_pow harnesses with unbounded u32 exponents hit CBMC's 10-minute timeout because 128-bit bitvector multiplication is extremely expensive. Add a dedicated macro that constrains exp <= 10 with unwind(5), sufficient to cover both the non-saturating and saturating code paths while keeping verification tractable.
…sion Same fix as saturating_pow_128: use a dedicated macro with exp <= 10 and #[kani::unwind(5)] for the 128-bit checked_pow harnesses.
d41f3ea to
9d26114
Compare
|
CI is passing — ready for review. |
There was a problem hiding this comment.
Pull request overview
This PR expands Kani-based verification coverage for core::num::NonZero* operations (Challenge 12), and adjusts checked_pow implementations to avoid CBMC/Kani interference from a trivial loop-invariant annotation.
Changes:
- Add a large set of new Kani verification harnesses under
core::num::nonzero::verifyfor many remainingNonZerooperations (bit ops, byte-order, bitor, arithmetic, pow, signed/unsigned-only ops, andfrom_mut). - Remove
#[safety::loop_invariant(true)]fromchecked_powloops in both unsigned and signed integer macro implementations to prevent CBMC assigns-check interference during verification. - Add bounded-unwind / bounded-exponent variants for 128-bit pow harnesses to keep verification tractable.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
library/core/src/num/nonzero.rs |
Adds many new Kani harnesses for NonZero* APIs in mod verify. |
library/core/src/num/uint_macros.rs |
Removes a trivial loop-invariant annotation from checked_pow’s loop. |
library/core/src/num/int_macros.rs |
Removes the same trivial loop-invariant annotation from signed checked_pow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| nonzero_check_isqrt!(core::num::NonZeroU8, nonzero_check_isqrt_u8); | ||
| nonzero_check_isqrt!(core::num::NonZeroU16, nonzero_check_isqrt_u16); | ||
| nonzero_check_isqrt!(core::num::NonZeroU32, nonzero_check_isqrt_u32); |
There was a problem hiding this comment.
NonZero::isqrt() is implemented for all unsigned nonzero types (u8/u16/u32/u64/u128/usize), but the verification harnesses here only cover u8/u16/u32. If the goal is to verify all remaining NonZero operations across all integer widths, add harnesses for NonZeroU64/NonZeroU128/NonZeroUsize as well (or document/encode an explicit bound or performance rationale for excluding the wider types).
| nonzero_check_isqrt!(core::num::NonZeroU32, nonzero_check_isqrt_u32); | |
| nonzero_check_isqrt!(core::num::NonZeroU32, nonzero_check_isqrt_u32); | |
| nonzero_check_isqrt!(core::num::NonZeroU64, nonzero_check_isqrt_u64); | |
| nonzero_check_isqrt!(core::num::NonZeroU128, nonzero_check_isqrt_u128); | |
| nonzero_check_isqrt!(core::num::NonZeroUsize, nonzero_check_isqrt_usize); |
Summary
Resolves #71 (Challenge 12: Safety of NonZero)
Adds 376 new Kani verification harnesses for all remaining NonZero functions specified in the challenge, covering:
count_ones,swap_bytes,reverse_bits,rotate_left,rotate_right(12 types each)from_be,from_le,to_be,to_le(12 types each)NonZero|NonZero,NonZero|T,T|NonZero(12 types each)checked_mul,saturating_mul,checked_add,saturating_add(unsigned-only for add)checked_pow,saturating_pow(12 types each)checked_next_power_of_two,midpoint,isqrtneg,abs,checked_abs,overflowing_abs,saturating_abs,wrapping_abs,unsigned_abs,checked_neg,overflowing_neg,wrapping_negfrom_mutChanges
library/core/src/num/nonzero.rs: 376 new verification harnesses inmod verifylibrary/core/src/num/uint_macros.rs: Remove trivial#[safety::loop_invariant(true)]fromchecked_powthat caused CBMC assigns check interference withNonZero::new_uncheckedverificationlibrary/core/src/num/int_macros.rs: Same loop_invariant removal for signed typesVerification
All 385 harnesses pass (376 new + 9 existing):
Run with: