Contracts and Harnesses for <*mut T>::add, sub and offset - #113
Conversation
Added unit type proofs for mut ptr
implemented integer type proof for contract for fn add, sub and offset
Verify/ptr mut composite
Combines macros for different types.
…allocation api, modified their proof for harness accordingly
Verify/ptr mut refactor harness
|
@zhassan-aws Hi the proofs have been updated to use pointer generator, however after the update we encountered a strange test failure, probably a bug: the test case All other proofs generated by the same macro work fine. Is there any possible cause for this problem? For now, we have to skip this test case by commenting it out. Update: The const counterpart |
|
@celinval encountered the same issue in #37 (comment). @celinval were you able to figure out what is causing the error and whether there's a workaround? |
|
Yes, the problem is that the pointer generator code is likely using the API you are trying to verify. For the harness that is failing, you won't be able to use the generator as is today. Sorry! |
…-checking#625) The requires/ensures clauses of the pointer arithmetic operations (`<*mut T>::{offset,add,sub}`, `<*const T>::{offset,add,sub}`, `NonNull::{add,sub}`, `NonNull::offset_from_unsigned`) demand `same_allocation` unconditionally (modulo a ZST escape), although the documented semantics explicitly permit zero-sized offsets on any pointer, including dangling ones: only "if the computed offset is non-zero, then self must be derived from a pointer to some allocated object". The stricter-than-documented clauses are violated by legitimate std code: empty slices may be backed by dangling pointers (`slice::from_raw_parts(ptr, 0)` for arbitrary aligned non-null `ptr` — exactly what `slice::iter`'s own `any_slice` helper generates), whereupon `Iter::new` computes `ptr.add(0)` and `len()` computes `end.offset_from_unsigned(begin)` on two equal dangling pointers. With dependency contracts asserted (the Kani default since model-checking/kani#3802), the `slice::iter::verify::verify_tup` harnesses fail on these clauses — and evaluating `same_allocation` on an allocation-less pointer is additionally a Kani unsupported construct ("Kani does not support reasoning about pointer to unallocated memory"). CI currently masks this via `--no-assert-contracts`. This PR adds the documented escape hatches: `count == 0 ||` ahead of the same-allocation disjunct in offset/add/sub requires and ensures — matching the precedent already present in `NonNull::offset` — and an equal-address escape in `NonNull::offset_from_unsigned`, matching the precedent in `<*const T>::offset_from`. Blame: the unconditional clauses date back to the original contract PRs model-checking#113 (014965a) and model-checking#93 (688b15b) and siblings. Verified with Kani 152c6a8c + CBMC 6.10.0: * `slice::iter::verify::verify_tup::{check_next_back_unchecked,check_advance_back_by}` now pass with contracts asserted; * all 265 proof harnesses matching `non_null_check_{add,sub,offset_from_unsigned}` and `ptr::verify::check_{mut,const}_{add,sub,offset}` pass both with and without `--no-assert-contracts`. Together with model-checking#622, model-checking#623, model-checking#624 and model-checking/kani#4709/rust-lang#4710, this resolves all verdict differences found on a 125-harness sample when running without `--no-assert-contracts`, except `non_null_check_from_raw_part_trait` (Kani's "unstable vtable comparison 'Eq'" limitation, reached by `as_ptr`'s postcondition on a `dyn Trait` pointee — tracked separately). By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Towards #76
Changes
<*mut T>::add,<*mut T>::suband<*mut T>::offsetBy submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.