Skip to content

Commit 62f76d2

Browse files
authored
Restrict MaybeUninit trait impls to fix soundness (#308)
Previously, we implemented `FromZeroes` and `FromBytes` for `MaybeUninit<T>` with no bound on `T`. This resulted in a soundness hole in which `T` - and thus `MaybeUninit<T>` - could contain an `UnsafeCell`, which is a violation of the contracts of `FromZeroes` and `FromBytes`. This is a breaking change, but it's very unlikely to be one that code is currently relying on, especially given that the 0.7.x release train was published very recently. Thus, in this commit, we publish 0.7.3, and we will yank 0.7.{0,1,2} as soon as 0.7.3 is published. Fixes #299
1 parent cb20ba0 commit 62f76d2

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
[package]
1212
edition = "2021"
1313
name = "zerocopy"
14-
version = "0.7.2"
14+
version = "0.7.3"
1515
authors = ["Joshua Liebow-Feeser <[email protected]>"]
1616
description = "Utilities for zero-copy parsing and serialization"
1717
license = "BSD-2-Clause"
@@ -55,7 +55,7 @@ simd-nightly = ["simd"]
5555
__internal_use_only_features_that_work_on_stable = ["alloc", "simd"]
5656

5757
[dependencies]
58-
zerocopy-derive = { version = "=0.7.2", path = "zerocopy-derive", optional = true }
58+
zerocopy-derive = { version = "=0.7.3", path = "zerocopy-derive", optional = true }
5959

6060
[dependencies.byteorder]
6161
version = "1.3"
@@ -66,7 +66,7 @@ optional = true
6666
# zerocopy-derive remain equal, even if the 'derive' feature isn't used.
6767
# See: https://github.com/matklad/macro-dep-test
6868
[target.'cfg(any())'.dependencies]
69-
zerocopy-derive = { version = "=0.7.2", path = "zerocopy-derive" }
69+
zerocopy-derive = { version = "=0.7.3", path = "zerocopy-derive" }
7070

7171
[dev-dependencies]
7272
rand = "0.6"
@@ -78,4 +78,4 @@ static_assertions = "1.1"
7878
# CI test failures.
7979
trybuild = "=1.0.80"
8080
# In tests, unlike in production, zerocopy-derive is not optional
81-
zerocopy-derive = { version = "=0.7.2", path = "zerocopy-derive" }
81+
zerocopy-derive = { version = "=0.7.3", path = "zerocopy-derive" }

src/lib.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -996,13 +996,23 @@ safety_comment! {
996996
//
997997
/// SAFETY:
998998
/// - `FromZeroes`, `FromBytes`: `MaybeUninit<T>` has no restrictions on its
999-
/// contents.
999+
/// contents. Unfortunately, in addition to bit validity, `FromZeroes` and
1000+
/// `FromBytes` also require that implementers contain no `UnsafeCell`s.
1001+
/// Thus, we require `T: FromZeroes` and `T: FromBytes` in order to ensure
1002+
/// that `T` - and thus `MaybeUninit<T>` - contains to `UnsafeCell`s.
1003+
/// Thus, requiring that `T` implement each of these traits is sufficient
10001004
/// - `Unaligned`: `MaybeUninit<T>` is guaranteed by its documentation [1]
10011005
/// to have the same alignment as `T`.
10021006
///
1003-
/// [1] https://doc.rust-lang.org/nightly/core/mem/union.MaybeUninit.html#layout-1
1004-
unsafe_impl!(T => FromZeroes for MaybeUninit<T>);
1005-
unsafe_impl!(T => FromBytes for MaybeUninit<T>);
1007+
/// [1]
1008+
/// https://doc.rust-lang.org/nightly/core/mem/union.MaybeUninit.html#layout-1
1009+
///
1010+
/// TODO(https://github.com/google/zerocopy/issues/251): If we split
1011+
/// `FromBytes` and `RefFromBytes`, or if we introduce a separate
1012+
/// `NoCell`/`Freeze` trait, we can relax the trait bounds for `FromZeroes`
1013+
/// and `FromBytes`.
1014+
unsafe_impl!(T: FromZeroes => FromZeroes for MaybeUninit<T>);
1015+
unsafe_impl!(T: FromBytes => FromBytes for MaybeUninit<T>);
10061016
unsafe_impl!(T: Unaligned => Unaligned for MaybeUninit<T>);
10071017
assert_unaligned!(MaybeUninit<()>, MaybeUninit<u8>);
10081018
}
@@ -4059,7 +4069,7 @@ mod tests {
40594069
assert_impls!(ManuallyDrop<[NotZerocopy]>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
40604070

40614071
assert_impls!(MaybeUninit<u8>: FromZeroes, FromBytes, Unaligned, !AsBytes);
4062-
assert_impls!(MaybeUninit<NotZerocopy>: FromZeroes, FromBytes, !AsBytes, !Unaligned);
4072+
assert_impls!(MaybeUninit<NotZerocopy>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
40634073

40644074
assert_impls!(Wrapping<u8>: FromZeroes, FromBytes, AsBytes, Unaligned);
40654075
assert_impls!(Wrapping<NotZerocopy>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned);

zerocopy-derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[package]
66
edition = "2021"
77
name = "zerocopy-derive"
8-
version = "0.7.2"
8+
version = "0.7.3"
99
authors = ["Joshua Liebow-Feeser <[email protected]>"]
1010
description = "Custom derive for traits from the zerocopy crate"
1111
license = "BSD-2-Clause"

0 commit comments

Comments
 (0)