Skip to content

Commit

Permalink
Fix undefined behavior on some CPUs
Browse files Browse the repository at this point in the history
  • Loading branch information
FssAy committed Mar 1, 2024
1 parent 6018cc2 commit de1d17c
Showing 1 changed file with 107 additions and 6 deletions.
113 changes: 107 additions & 6 deletions src/syntatic/header.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::mem::size_of;
use super::Data;

pub type HeaderDataSize = u32;
pub type HeaderDataType = u16;
pub type HeaderQueue = u8;

#[repr(packed)] // required for network exchange
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// The Header part of the Box.
///
/// It can be copied or cloned cheaply.
Expand All @@ -14,14 +14,14 @@ pub type HeaderQueue = u8;
/// - data_type - unsigned 16 bit value used to inform the reader about the type of incoming Data
/// - queue - unsigned 8 bit value used to inform the server to which queue use to handle the Box
pub struct Header {
data_size: HeaderDataSize, // cannot access due to packed representation
data_size: HeaderDataSize,
data_type: HeaderDataType,
queue: HeaderQueue,
}

impl Header {
/// Size of the Header in bytes.
pub const SIZE: usize = std::mem::size_of::<Header>();
pub const SIZE: usize = size_of::<HeaderDataSize>() + size_of::<HeaderDataType>() + size_of::<HeaderQueue>();

// getters needed due to packed representation of the struct

Expand Down Expand Up @@ -75,13 +75,114 @@ impl Header {
/// Same as `Header::into_array`
impl Into<[u8; Header::SIZE]> for Header {
fn into(self) -> [u8; Header::SIZE] {
unsafe { std::mem::transmute(self) }
let mut buffer = [0x00_u8; Header::SIZE];
let buffer_ptr = buffer.as_mut_ptr();

let data_size_ptr = self.data_size.to_le_bytes().as_ptr();
let data_type_ptr = self.data_type.to_le_bytes().as_ptr();
let queue_ptr = self.queue.to_le_bytes().as_ptr();

let mut cursor = 0;

unsafe {
copy_bytes_to(
data_size_ptr,
buffer_ptr,
size_of::<HeaderDataSize>(),
&mut cursor,
);

copy_bytes_to(
data_type_ptr,
buffer_ptr,
size_of::<HeaderDataType>(),
&mut cursor,
);

copy_bytes_to(
queue_ptr,
buffer_ptr,
size_of::<HeaderQueue>(),
&mut cursor,
);
}

buffer
}
}

/// Same as `Header::from_array`
impl From<[u8; Header::SIZE]> for Header {
fn from(bytes: [u8; Header::SIZE]) -> Self {
unsafe { std::mem::transmute(bytes) }
let mut buffer_data_size = [0x00_u8; size_of::<HeaderDataSize>()];
let mut buffer_data_type = [0x00_u8; size_of::<HeaderDataType>()];
let mut buffer_queue = [0x00_u8; size_of::<HeaderQueue>()];

let bytes_ptr = bytes.as_ptr();

let mut cursor = 0;

unsafe {
copy_bytes_from(
bytes_ptr,
buffer_data_size.as_mut_ptr(),
size_of::<HeaderDataSize>(),
&mut cursor,
);

copy_bytes_from(
bytes_ptr,
buffer_data_type.as_mut_ptr(),
size_of::<HeaderDataType>(),
&mut cursor,
);

copy_bytes_from(
bytes_ptr,
buffer_queue.as_mut_ptr(),
size_of::<HeaderQueue>(),
&mut cursor,
);
}

Self {
data_size: HeaderDataSize::from_le_bytes(buffer_data_size),
data_type: HeaderDataType::from_le_bytes(buffer_data_type),
queue: HeaderQueue::from_le_bytes(buffer_queue),
}
}
}

/// Copies bytes into one specific buffer.
///
/// # Args
/// - src - pointer to a byte array from which bytes will be copied
/// - dst - pointer to a buffer
/// - count - amount of bytes to copy from src (should be size_of src)
/// - cursor - cursor over the buffer
unsafe fn copy_bytes_to(src: *const u8, dst: *mut u8, count: usize, cursor: &mut usize) {
std::ptr::copy(
src,
dst.add(*cursor),
count
);

*cursor += count;
}

/// Copies bytes from one specific array.
///
/// # Args
/// - src - pointer to an array
/// - dst - pointer to a buffer into which bytes will be copied to
/// - count - amount of bytes to copy from src (should be size_of dst)
/// - cursor - cursor over the array
unsafe fn copy_bytes_from(src: *const u8, dst: *mut u8, count: usize, cursor: &mut usize) {
std::ptr::copy(
src.add(*cursor),
dst,
count
);

*cursor += count;
}

0 comments on commit de1d17c

Please sign in to comment.