mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-15 08:48:52 +00:00
Fix Rust UB problems (#6393)
* Fix miri problems by assuming alignment is 1 in rust * Removed is_aligned fn from rust verifier. * Add back is_aligned, but make it w.r.t. buffer[0] * touch unused variable * touch unused variable * +nightly * Move Rust miri testing into its own docker * fix bash * missing one endian conversion * fix endianness2 * format stuff Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flatbuffers"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2018"
|
||||
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -150,11 +150,13 @@ pub fn byte_swap_f64(x: f64) -> f64 {
|
||||
/// endian conversion, if necessary.
|
||||
#[inline]
|
||||
pub fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
|
||||
let sz = size_of::<T>();
|
||||
let mut_ptr = (&mut s[..sz]).as_mut_ptr() as *mut T;
|
||||
let val = x.to_little_endian();
|
||||
let x_le = x.to_little_endian();
|
||||
unsafe {
|
||||
*mut_ptr = val;
|
||||
core::ptr::copy_nonoverlapping(
|
||||
&x_le as *const T as *const u8,
|
||||
s.as_mut_ptr() as *mut u8,
|
||||
size_of::<T>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,18 +164,22 @@ pub fn emplace_scalar<T: EndianScalar>(s: &mut [u8], x: T) {
|
||||
/// Performs endian conversion, if necessary.
|
||||
#[inline]
|
||||
pub fn read_scalar_at<T: EndianScalar>(s: &[u8], loc: usize) -> T {
|
||||
let buf = &s[loc..loc + size_of::<T>()];
|
||||
read_scalar(buf)
|
||||
read_scalar(&s[loc..])
|
||||
}
|
||||
|
||||
/// Read an EndianScalar from the provided byte slice. Performs endian
|
||||
/// conversion, if necessary.
|
||||
#[inline]
|
||||
pub fn read_scalar<T: EndianScalar>(s: &[u8]) -> T {
|
||||
let sz = size_of::<T>();
|
||||
|
||||
let p = (&s[..sz]).as_ptr() as *const T;
|
||||
let x = unsafe { *p };
|
||||
|
||||
let mut mem = core::mem::MaybeUninit::<T>::uninit();
|
||||
// Since [u8] has alignment 1, we copy it into T which may have higher alignment.
|
||||
let x = unsafe {
|
||||
core::ptr::copy_nonoverlapping(
|
||||
s.as_ptr(),
|
||||
mem.as_mut_ptr() as *mut u8,
|
||||
size_of::<T>()
|
||||
);
|
||||
mem.assume_init()
|
||||
};
|
||||
x.from_little_endian()
|
||||
}
|
||||
|
||||
@@ -232,12 +232,16 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||
self.num_tables = 0;
|
||||
self.num_tables = 0;
|
||||
}
|
||||
/// Check that there really is a T in there.
|
||||
/// Checks `pos` is aligned to T's alignment. This does not mean `buffer[pos]` is aligned w.r.t
|
||||
/// memory since `buffer: &[u8]` has alignment 1.
|
||||
///
|
||||
/// ### WARNING
|
||||
/// This does not work for flatbuffers-structs as they have alignment 1 according to
|
||||
/// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t.
|
||||
/// `buffer[0]`. TODO(caspern).
|
||||
#[inline]
|
||||
fn is_aligned<T>(&self, pos: usize) -> Result<()> {
|
||||
// Safe because we're not dereferencing.
|
||||
let p = unsafe { self.buffer.as_ptr().add(pos) };
|
||||
if (p as usize) % std::mem::align_of::<T>() == 0 {
|
||||
if pos % std::mem::align_of::<T>() == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(InvalidFlatbuffer::Unaligned {
|
||||
@@ -259,6 +263,7 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
/// Check that there really is a T in there.
|
||||
#[inline]
|
||||
pub fn in_buffer<T>(&mut self, pos: usize) -> Result<()> {
|
||||
self.is_aligned::<T>(pos)?;
|
||||
|
||||
Reference in New Issue
Block a user