Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 3 additions & 18 deletions zerocopy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5987,11 +5987,7 @@ pub unsafe trait IntoBytes {
{
let src = self.as_bytes();
if dst.len() == src.len() {
// SAFETY: Within this branch of the conditional, we have ensured
// that `dst.len()` is equal to `src.len()`. Neither the size of the
// source nor the size of the destination change between the above
// size check and the invocation of `copy_unchecked`.
unsafe { util::copy_unchecked(src, dst) }
util::copy_prefix(src, dst);
Ok(())
} else {
Err(SizeError::new(self))
Expand Down Expand Up @@ -6074,12 +6070,7 @@ pub unsafe trait IntoBytes {
let src = self.as_bytes();
match dst.get_mut(..src.len()) {
Some(dst) => {
// SAFETY: Within this branch of the `match`, we have ensured
// through fallible subslicing that `dst.len()` is equal to
// `src.len()`. Neither the size of the source nor the size of
// the destination change between the above subslicing operation
// and the invocation of `copy_unchecked`.
unsafe { util::copy_unchecked(src, dst) }
util::copy_prefix(src, dst);
Ok(())
}
None => Err(SizeError::new(self)),
Expand Down Expand Up @@ -6181,13 +6172,7 @@ pub unsafe trait IntoBytes {
// than panicking.
return Err(SizeError::new(self));
};
// SAFETY: Through fallible subslicing of `dst`, we have ensured that
// `dst.len()` is equal to `src.len()`. Neither the size of the source
// nor the size of the destination change between the above subslicing
// operation and the invocation of `copy_unchecked`.
unsafe {
util::copy_unchecked(src, dst);
}
util::copy_prefix(src, dst);
Ok(())
}

Expand Down
26 changes: 26 additions & 0 deletions zerocopy/src/proof_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,29 @@ pub(crate) fn nonzero_u16_from_ne_bytes(bytes: [u8; 2]) -> Option<core::num::Non
pub(crate) fn copy_snapshot<T: Copy>(value: &T) -> T {
*value
Comment on lines +397 to +398

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ground snapshot dereferencing in a language contract

When the copy proof uses this helper to establish the pre-call source and destination values, the cited moved/copied-place rule explains what happens after a place has been selected, but it does not establish that *value denotes the referent supplied by the caller. Add the versioned dereference-result contract (and retain the explanation that this safe helper is independent of the target); otherwise the frame oracle's claimed snapshot semantics lack the complete normative basis required by agent_docs/validation.md.

AGENTS.md reference: zerocopy/AGENTS.md:L67-L71

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the current revision. copy_snapshot now cites the full Rust 1.93 language chain: the dereference-result rule establishes that *value denotes the referent; the block rule establishes that the function-body block evaluates its final operand in value context; and the moved/copied-place rule establishes that this copies the T: Copy value. The comment explicitly identifies the helper as safe and independent of zerocopy, and limits its observation to value rather than allocation identity or independent storage.

Authored by an AI agent acting on Josh Liebow-Feeser's behalf.

}

// Compare ordered byte values without treating slice or array `PartialEq` as
// an implicit oracle. `slice::len` returns each slice's element count,
// while the factored `assert_same_usize` supplies the documented equality
// observation above. The first assertion therefore requires equal element
// counts. `slice::iter` yields every item from start to end [1],
// `Iterator::copied` copies those items and `Iterator::eq` compares the two
// sequences [2], and `u8::eq` supplies element equality [3]. Rust specifies
// that the final `assert!` panics when that equality expression
// is false and cannot be disabled [4], so—under Kani's assertion/panic
// translation—an ordered-value mismatch cannot silently pass the harness.
// These safe operations call no zerocopy target, so they are
// independent of that target implementation, but not of the compiler,
// standard library, or Kani model. They establish values only, not storage
// identity or provenance.
//
// [1] https://doc.rust-lang.org/1.93.0/std/primitive.slice.html#method.len
// https://doc.rust-lang.org/1.93.0/std/primitive.slice.html#method.iter
// [2] https://doc.rust-lang.org/1.93.0/std/iter/trait.Iterator.html#method.copied
// https://doc.rust-lang.org/1.93.0/std/iter/trait.Iterator.html#method.eq
// [3] https://doc.rust-lang.org/1.93.0/std/primitive.u8.html#impl-PartialEq-for-u8
// [4] https://doc.rust-lang.org/1.93.0/std/macro.assert.html
pub(crate) fn assert_same_u8_elements(actual: &[u8], expected: &[u8]) {
assert_same_usize(actual.len(), expected.len());
assert!(actual.iter().copied().eq(expected.iter().copied()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Cite the assertion contract used by the byte oracle

Every new byte and u32 postcondition ultimately depends on this assert!, but the oracle account cites only the contracts that compute the boolean returned by Iterator::eq; it never cites the Rust 1.93 assert! contract connecting a false result to proof failure. Add that versioned standard-library citation and explain that this safe assertion mechanism is independent of the zerocopy targets, so the documented oracle chain actually establishes that unequal bytes cannot pass verification.

AGENTS.md reference: zerocopy/AGENTS.md:L67-L71

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the current revision. The shared ordered-byte observer now cites Rust 1.93’s assert! contract: a false condition panics and the assertion cannot be disabled. The documentation connects that rule to Iterator::eq, so unequal ordered bytes cannot pass under Kani’s assertion/panic translation, and classifies that translation as part of the compiler/Kani trust boundary rather than a zerocopy premise.

Authored by an AI agent acting on Josh Liebow-Feeser's behalf.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bafebedf715d: the harness now cites the precise assert! contract used by the proof.

Authored by an AI agent acting on Josh Liebow-Feeser's behalf.

}
Loading
Loading