Skip to content

Commit

Permalink
safety: ensure that we dereference an aligned pointer
Browse files Browse the repository at this point in the history
Previously, we were copying data to a `[u8; 8]` and then dereferencing a
pointer to `[u8; 8]` as if it were a `u64`. However, this is actually
undefined behavior since `[u8; 8]` has a smaller alignment than `u64`.

To fix this, we start with a `u64` such that we are guaranteed correct
alignment.

Closes #157
  • Loading branch information
BurntSushi committed Jan 10, 2020
1 parent 0582376 commit 15e9281
Showing 1 changed file with 12 additions and 12 deletions.
24 changes: 12 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1979,26 +1979,26 @@ impl ByteOrder for BigEndian {
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
let mut out = [0u8; 8];
let ptr_out = out.as_mut_ptr();
let mut out = 0u64;
let ptr_out = &mut out as *mut u64 as *mut u8;
unsafe {
copy_nonoverlapping(
buf.as_ptr(), ptr_out.offset((8 - nbytes) as isize), nbytes);
(*(ptr_out as *const u64)).to_be()
}
out.to_be()
}

#[cfg(byteorder_i128)]
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
let mut out = [0u8; 16];
let ptr_out = out.as_mut_ptr();
let mut out: u128 = 0;
let ptr_out = &mut out as *mut u128 as *mut u8;
unsafe {
copy_nonoverlapping(
buf.as_ptr(), ptr_out.offset((16 - nbytes) as isize), nbytes);
(*(ptr_out as *const u128)).to_be()
}
out.to_be()
}

#[inline]
Expand Down Expand Up @@ -2194,24 +2194,24 @@ impl ByteOrder for LittleEndian {
#[inline]
fn read_uint(buf: &[u8], nbytes: usize) -> u64 {
assert!(1 <= nbytes && nbytes <= 8 && nbytes <= buf.len());
let mut out = [0u8; 8];
let ptr_out = out.as_mut_ptr();
let mut out = 0u64;
let ptr_out = &mut out as *mut u64 as *mut u8;
unsafe {
copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes);
(*(ptr_out as *const u64)).to_le()
}
out.to_le()
}

#[cfg(byteorder_i128)]
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
let mut out = [0u8; 16];
let ptr_out = out.as_mut_ptr();
let mut out: u128 = 0;
let ptr_out = &mut out as *mut u128 as *mut u8;
unsafe {
copy_nonoverlapping(buf.as_ptr(), ptr_out, nbytes);
(*(ptr_out as *const u128)).to_le()
}
out.to_le()
}

#[inline]
Expand Down

0 comments on commit 15e9281

Please sign in to comment.