Skip to content

Commit

Permalink
Add debug assertions related to safety conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
CodesInChaos authored and CodesInChaos committed Mar 19, 2023
1 parent 92ed4e8 commit 8eeb175
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/context/cdf_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,10 @@ trait CDFContextLogOps: CDFContextLogSize {
let capacity = log.data.capacity();
debug_assert!(new_len <= capacity);
let dst = log.data.as_mut_ptr().add(len);
// This reads beyond the end of `cdf`.
// Since it's part of a larger data structure, the out-of-bounds data is valid.
// However this violates the stacked-borrows memory model and is technically undefined behavior.
// See https://github.com/xiph/rav1e/issues/3166
dst.copy_from_nonoverlapping(cdf.as_ptr(), Self::CDF_LEN_MAX);
*dst.add(Self::CDF_LEN_MAX) = offset as u16;
log.data.set_len(new_len);
Expand All @@ -615,14 +619,20 @@ trait CDFContextLogOps: CDFContextLogSize {
) {
let base = fc as *mut _ as *mut u8;
let mut len = log.data.len();
debug_assert!(len % (Self::CDF_LEN_MAX + 1) == 0);
// SAFETY: We use unchecked pointers here for performance.
// Since we know the length, we can ensure not to go OOB.
unsafe {
let mut src = log.data.as_mut_ptr().add(len);
while len > checkpoint {
debug_assert!(len >= Self::CDF_LEN_MAX + 1);
len -= Self::CDF_LEN_MAX + 1;
src = src.sub(Self::CDF_LEN_MAX + 1);
let offset = *src.add(Self::CDF_LEN_MAX) as usize;
debug_assert!(
offset + Self::CDF_LEN_MAX * mem::size_of::<u16>()
<= mem::size_of::<CDFContext>()
);
let dst = base.add(offset) as *mut u16;
dst.copy_from_nonoverlapping(src, Self::CDF_LEN_MAX);
}
Expand Down
3 changes: 3 additions & 0 deletions src/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,13 @@ pub(crate) mod rust {

// SAFETY: The length of data must be 16.
unsafe fn hadamard4x4(data: &mut [i32]) {
debug_assert_eq!(data.len(), 16);
hadamard2d::<{ 4 * 4 }, 4, 4>(&mut *(data.as_mut_ptr() as *mut [i32; 16]));
}

// SAFETY: The length of data must be 64.
unsafe fn hadamard8x8(data: &mut [i32]) {
debug_assert_eq!(data.len(), 64);
hadamard2d::<{ 8 * 8 }, 8, 8>(&mut *(data.as_mut_ptr() as *mut [i32; 64]));
}

Expand All @@ -166,6 +168,7 @@ pub(crate) mod rust {
// Size of hadamard transform should be 4x4 or 8x8
// 4x* and *x4 use 4x4 and all other use 8x8
let size: usize = w.min(h).min(8);
debug_assert!(size == 4 || size == 8);
let tx2d = if size == 4 { hadamard4x4 } else { hadamard8x8 };

let mut sum: u64 = 0;
Expand Down
6 changes: 6 additions & 0 deletions src/lrf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ pub(crate) mod rust {
let ssq = get_integral_square(iimg_sq, iimg_stride, x, y, d);
let (reta, retb) =
sgrproj_sum_finish::<BD>(ssq, sum, n as u32, one_over_n, s);
debug_assert!(x < af.len());
*af.get_unchecked_mut(x) = reta;
debug_assert!(x < bf.len());
*bf.get_unchecked_mut(x) = retb;
}
}
Expand Down Expand Up @@ -369,9 +371,13 @@ unsafe fn get_integral_square(
iimg: &[u32], stride: usize, x: usize, y: usize, size: usize,
) -> u32 {
// Cancel out overflow in iimg by using wrapping arithmetic
debug_assert!(y * stride + x < iimg.len());
let top_left = *iimg.get_unchecked(y * stride + x);
debug_assert!(y * stride + x + size < iimg.len());
let top_right = *iimg.get_unchecked(y * stride + x + size);
debug_assert!((y + size) * stride + x < iimg.len());
let bottom_left = *iimg.get_unchecked((y + size) * stride + x);
debug_assert!((y + size) * stride + x + size < iimg.len());
let bottom_right = *iimg.get_unchecked((y + size) * stride + x + size);
top_left
.wrapping_add(bottom_right)
Expand Down
2 changes: 1 addition & 1 deletion src/util/align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<T> AlignedBoxedSlice<T> {
}

const fn layout(len: usize) -> Layout {
// SAFETY: We are ensuring that `align` is non-zero and is a multiple of 2.
// SAFETY: We are ensuring that `align` is non-zero and is a power of 2.
unsafe {
Layout::from_size_align_unchecked(
len * mem::size_of::<T>(),
Expand Down

0 comments on commit 8eeb175

Please sign in to comment.