Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

struct AlignedVec: Verify alignment for T #1369

Merged
merged 1 commit into from
Nov 11, 2024
Merged
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
25 changes: 25 additions & 0 deletions src/align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,14 @@ impl<T: Copy, C: AlignedByteChunk> AlignedVec<T, C> {
assert!(mem::size_of::<C>() == mem::align_of::<C>());
}

const fn check_inner_type_is_aligned() {
assert!(mem::align_of::<T>() <= mem::align_of::<C>());
}

pub const fn new() -> Self {
Self::check_byte_chunk_type_is_aligned();
Self::check_inner_type_is_aligned();

Self {
inner: Vec::new(),
len: 0,
Expand All @@ -172,13 +178,19 @@ impl<T: Copy, C: AlignedByteChunk> AlignedVec<T, C> {
pub fn as_slice(&self) -> &[T] {
// SAFETY: The first `len` elements have been
// initialized to `T`s in `Self::resize_with`.
// SAFETY: The pointer is sufficiently aligned,
// as the chunks are always over-aligned with
// respect to `T`.
unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
}

/// Extract a mutable slice of the entire vector.
pub fn as_mut_slice(&mut self) -> &mut [T] {
// SAFETY: The first `len` elements have been
// initialized to `T`s in `Self::resize_with`.
// SAFETY: The pointer is sufficiently aligned,
// as the chunks are always over-aligned with
// respect to `T`.
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
}

Expand Down Expand Up @@ -208,6 +220,9 @@ impl<T: Copy, C: AlignedByteChunk> AlignedVec<T, C> {
for offset in old_len..new_len {
// SAFETY: We've allocated enough space to write
// up to `new_len` elements into the buffer.
// SAFETY: The pointer is sufficiently aligned,
// as the chunks are always over-aligned with
// respect to `T`.
unsafe { self.as_mut_ptr().add(offset).write(value) };
}

Expand Down Expand Up @@ -288,3 +303,13 @@ fn align_vec_fails() {
// work.
assert_eq!(v.as_slice()[isize::MAX as usize], 0);
}

#[test]
#[should_panic]
fn under_aligned_storage_fails() {
let mut v = AlignedVec::<u128, Align1<[u8; 1]>>::new();

// Would be UB: unaligned write of type u128 to pointer aligned to 1 (or 8 in most allocators,
// but statically we only ensure an alignment of 1).
v.resize(1, 0u128);
}
Loading