Avoid len check in `ArrayVec::spare_capacity_mut`
What changed, and why it matters
This commit changes an internal helper function in the rust-bitcoin library to skip a length safety check using Rust's `unsafe` keyword. The author argues this is safe because the type already relies on an internal invariant that the length never exceeds capacity. The change is small and performance-oriented, but it increases reliance on a manually maintained safety invariant.
Review the `ArrayVec` type to confirm the `len <= CAP` invariant is truly preserved across all constructors, mutation methods, and `unsafe` code paths. Consider adding debug-only assertions or fuzz tests to validate the invariant, and ensure Miri or similar tooling is used to check this code path.
Security signals we found
Introduction of `unsafe` block where none existed before
Use of `get_unchecked_mut` on a slice
Reliance on manually maintained type invariant for soundness
Change located in a module named `safety_boundary`
No accompanying test or invariant documentation expansion
Evidence from the diff
In internals/src/array_vec.rs, ArrayVec::spare_capacity_mut was changed from &mut self.data[self.len..] to an unsafe call to self.data.get_unchecked_mut(self.len..). The commit message justifies this by stating that self.len <= CAP is an existing invariant of the ArrayVec type. This removes a runtime bounds check in favor of trusting the invariant. The change is within a module explicitly named safety_boundary.
Changed components
internals/src/array_vec.rsArrayVec::spare_capacity_mutInspect captured patch +2 / −1
diff --git a/internals/src/array_vec.rs b/internals/src/array_vec.rs
index 322bdca7..a2cc2baa 100644
--- a/internals/src/array_vec.rs
+++ b/internals/src/array_vec.rs
@@ -63,7 +63,8 @@ mod safety_boundary {
/// Returns remaining spare capacity of the vector as a slice of `MaybeUninit<T>`.
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
- &mut self.data[self.len..]
+ // SOUNDNESS: self.len <= CAP is the invariant on the type
+ unsafe { self.data.get_unchecked_mut(self.len..) }
}
/// Forces the length to `new_len`.
Why this scored 26/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.