Skip to content

Commit 77583c2

Browse files
committed
Use aligned reads and writes in the abomonation implementation
1 parent 339a5e3 commit 77583c2

File tree

2 files changed

+136
-215
lines changed

2 files changed

+136
-215
lines changed

src/align/io.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use std::{
99
io::Write,
10-
mem,
10+
mem::{self, MaybeUninit},
1111
ptr::NonNull,
1212
};
1313

@@ -77,9 +77,27 @@ impl<W: Write> AlignedWriter<W> {
7777
self.written_so_far += 1;
7878
}
7979

80-
// Write down the binary data and exit
81-
// FIXME: Move write_bytes functionality here
82-
crate::write_bytes(&mut self.inner, data)?;
80+
// This is the correct way to reinterpret typed data as bytes, it
81+
// accounts for the fact that T may contain padding bytes.
82+
let bytes = std::slice::from_raw_parts(
83+
data.as_ptr() as *const MaybeUninit<u8>,
84+
data.len() * mem::size_of::<T>()
85+
);
86+
87+
// FIXME: Unfortunately, `Write::write_all()` expects initialized
88+
// bytes. This transmute is undefined behavior if T contains
89+
// uninitialized padding bytes.
90+
//
91+
// To resolve this UB, we'd need either a "freeze" operation
92+
// that turns uninitialized bytes into arbitrary initialized
93+
// bytes, or a `Write` interface that accepts uninit bytes.
94+
//
95+
// See this Rust internals forum topic for more discussion:
96+
// https://internals.rust-lang.org/t/writing-down-binary-data-with-padding-bytes/11197/
97+
//
98+
self.inner.write_all(mem::transmute::<&[MaybeUninit<u8>], &[u8]>(bytes))?;
99+
100+
// Keep track of the amount of emitted data and exit
83101
self.written_so_far += mem::size_of_val::<[T]>(data);
84102
Ok(())
85103
}

0 commit comments

Comments
 (0)