Skip to content

Commit 93751fb

Browse files
committed
Fix soundness of FromBytes::read_from_io on 0.8.x
See google#2319. Backport of google#2320. Includes a Miri test confirming the previous unsoundness.
1 parent 57fdc1b commit 93751fb

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/lib.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -4567,7 +4567,8 @@ pub unsafe trait FromBytes: FromZeros {
45674567
Self: Sized,
45684568
R: io::Read,
45694569
{
4570-
let mut buf = CoreMaybeUninit::<Self>::zeroed();
4570+
let mut buf = CoreMaybeUninit::<Self>::uninit();
4571+
buf.zero();
45714572
let ptr = Ptr::from_mut(&mut buf);
45724573
// SAFETY: `buf` consists entirely of initialized, zeroed bytes.
45734574
let ptr = unsafe { ptr.assume_validity::<invariant::Initialized>() };
@@ -6079,6 +6080,29 @@ mod tests {
60796080
assert_eq!(bytes, want);
60806081
}
60816082

6083+
#[test]
6084+
#[cfg(feature = "std")]
6085+
fn test_read_io_with_padding_soundness() {
6086+
#[derive(FromBytes)]
6087+
#[repr(C)]
6088+
struct WithPadding {
6089+
x: u8,
6090+
y: u16,
6091+
}
6092+
struct ReadsInRead;
6093+
impl std::io::Read for ReadsInRead {
6094+
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
6095+
if buf.iter().all(|&x| x == 0) {
6096+
Ok(buf.len())
6097+
} else {
6098+
buf.into_iter().for_each(|x| *x = 0);
6099+
Ok(buf.len())
6100+
}
6101+
}
6102+
}
6103+
assert!(matches!(WithPadding::read_from_io(ReadsInRead), Ok(WithPadding { x: 0, y: 0 })));
6104+
}
6105+
60826106
#[test]
60836107
#[cfg(feature = "std")]
60846108
fn test_read_write_io() {

0 commit comments

Comments
 (0)