1 // Copyright 2017 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::io;
6 use std::mem::size_of;
7 use std::mem::MaybeUninit;
8 use std::slice::from_raw_parts;
9 use std::slice::from_raw_parts_mut;
10
11 use zerocopy::AsBytes;
12 use zerocopy::FromBytes;
13 use zerocopy::LayoutVerified;
14
zerocopy_from_reader<R: io::Read, T: FromBytes>(mut read: R) -> io::Result<T>15 pub fn zerocopy_from_reader<R: io::Read, T: FromBytes>(mut read: R) -> io::Result<T> {
16 // Allocate on the stack via `MaybeUninit` to ensure proper alignment.
17 let mut out = MaybeUninit::zeroed();
18
19 // Safe because the pointer is valid and points to `size_of::<T>()` bytes of zeroes,
20 // which is a properly initialized value for `u8`.
21 let buf = unsafe { from_raw_parts_mut(out.as_mut_ptr() as *mut u8, size_of::<T>()) };
22 read.read_exact(buf)?;
23
24 // Safe because any bit pattern is considered a valid value for `T`.
25 Ok(unsafe { out.assume_init() })
26 }
27
zerocopy_from_mut_slice<T: FromBytes + AsBytes>(data: &mut [u8]) -> Option<&mut T>28 pub fn zerocopy_from_mut_slice<T: FromBytes + AsBytes>(data: &mut [u8]) -> Option<&mut T> {
29 let lv: LayoutVerified<&mut [u8], T> = LayoutVerified::new(data)?;
30 Some(lv.into_mut())
31 }
32
zerocopy_from_slice<T: FromBytes>(data: &[u8]) -> Option<&T>33 pub fn zerocopy_from_slice<T: FromBytes>(data: &[u8]) -> Option<&T> {
34 let lv: LayoutVerified<&[u8], T> = LayoutVerified::new(data)?;
35 Some(lv.into_ref())
36 }
37
38 /// Types for which it is safe to initialize from raw data.
39 ///
40 ///
41 /// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
42 ///
43 /// # Safety
44 /// A type `T` is `DataInit` if it can be initialized by reading its contents from a byte array.
45 /// This is generally true for all plain-old-data structs. It is notably not true for any type
46 /// that includes a reference.
47 ///
48 /// It is unsafe for `T` to be `DataInit` if `T` contains implicit padding. (LLVM considers access
49 /// to implicit padding to be undefined behavior, which can cause UB when working with `T`.
50 /// For details on structure padding in Rust, see
51 /// <https://doc.rust-lang.org/reference/type-layout.html#the-c-representation>.
52 pub unsafe trait DataInit: Copy + Send + Sync {
53 /// Converts a slice of raw data into a reference of `Self`.
54 ///
55 /// The value of `data` is not copied. Instead a reference is made from the given slice. The
56 /// value of `Self` will depend on the representation of the type in memory, and may change in
57 /// an unstable fashion.
58 ///
59 /// This will return `None` if the length of data does not match the size of `Self`, or if the
60 /// data is not aligned for the type of `Self`.
from_slice(data: &[u8]) -> Option<&Self>61 fn from_slice(data: &[u8]) -> Option<&Self> {
62 // Early out to avoid an unneeded `align_to` call.
63 if data.len() != size_of::<Self>() {
64 return None;
65 }
66
67 // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
68 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
69 // we don't have any unaligned references. This aliases a pointer, but because the pointer
70 // is from a const slice reference, there are no mutable aliases. Finally, the reference
71 // returned can not outlive data because they have equal implicit lifetime constraints.
72 match unsafe { data.align_to::<Self>() } {
73 ([], [mid], []) => Some(mid),
74 _ => None,
75 }
76 }
77
78 /// Copies the value of `Self` from the beginning of a slice of raw data.
79 ///
80 /// This will return `None` if the length of data is less than the size of `Self`, or if the
81 /// data is not aligned for the type of `Self`.
read_from_prefix(data: &[u8]) -> Option<Self>82 fn read_from_prefix(data: &[u8]) -> Option<Self> {
83 data.get(0..size_of::<Self>())
84 .and_then(|slice| Self::from_slice(slice))
85 .copied()
86 }
87
88 /// Converts a mutable slice of raw data into a mutable reference of `Self`.
89 ///
90 /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
91 /// reference are immediately reflected in `data`. The value of the returned `Self` will depend
92 /// on the representation of the type in memory, and may change in an unstable fashion.
93 ///
94 /// This will return `None` if the length of data does not match the size of `Self`, or if the
95 /// data is not aligned for the type of `Self`.
from_mut_slice(data: &mut [u8]) -> Option<&mut Self>96 fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
97 // Early out to avoid an unneeded `align_to_mut` call.
98 if data.len() != size_of::<Self>() {
99 return None;
100 }
101
102 // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
103 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
104 // we don't have any unaligned references. This aliases a pointer, but because the pointer
105 // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
106 // reference returned can not outlive data because they have equal implicit lifetime
107 // constraints.
108 match unsafe { data.align_to_mut::<Self>() } {
109 ([], [mid], []) => Some(mid),
110 _ => None,
111 }
112 }
113
114 /// Creates an instance of `Self` by copying raw data from an io::Read stream.
from_reader<R: io::Read>(mut read: R) -> io::Result<Self>115 fn from_reader<R: io::Read>(mut read: R) -> io::Result<Self> {
116 // Allocate on the stack via `MaybeUninit` to ensure proper alignment.
117 let mut out = MaybeUninit::zeroed();
118
119 // Safe because the pointer is valid and points to `size_of::<Self>()` bytes of zeroes,
120 // which is a properly initialized value for `u8`.
121 let buf = unsafe { from_raw_parts_mut(out.as_mut_ptr() as *mut u8, size_of::<Self>()) };
122 read.read_exact(buf)?;
123
124 // Safe because any bit pattern is considered a valid value for `Self`.
125 Ok(unsafe { out.assume_init() })
126 }
127
128 /// Converts a reference to `self` into a slice of bytes.
129 ///
130 /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
131 /// The value of bytes in the returned slice will depend on the representation of the type in
132 /// memory, and may change in an unstable fashion.
as_slice(&self) -> &[u8]133 fn as_slice(&self) -> &[u8] {
134 // Safe because the entire size of self is accessible as bytes because the trait guarantees
135 // it. The lifetime of the returned slice is the same as the passed reference, so that no
136 // dangling pointers will result from this pointer alias.
137 unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
138 }
139
140 /// Converts a mutable reference to `self` into a mutable slice of bytes.
141 ///
142 /// Because the slice is made from a reference to `self`, mutations to the returned slice are
143 /// immediately reflected in `self`. The value of bytes in the returned slice will depend on
144 /// the representation of the type in memory, and may change in an unstable fashion.
as_mut_slice(&mut self) -> &mut [u8]145 fn as_mut_slice(&mut self) -> &mut [u8] {
146 // Safe because the entire size of self is accessible as bytes because the trait guarantees
147 // it. The trait also guarantees that any combination of bytes is valid for this type, so
148 // modifying them in the form of a byte slice is valid. The lifetime of the returned slice
149 // is the same as the passed reference, so that no dangling pointers will result from this
150 // pointer alias. Although this does alias a mutable pointer, we do so by exclusively
151 // borrowing the given mutable reference.
152 unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
153 }
154 }
155
156 // All intrinsic types and arays of intrinsic types are DataInit. They are just numbers.
157 macro_rules! array_data_init {
158 ($T:ty, $($N:expr)+) => {
159 $(
160 unsafe impl DataInit for [$T; $N] {}
161 )+
162 }
163 }
164 macro_rules! data_init_type {
165 ($($T:ident),*) => {
166 $(
167 unsafe impl DataInit for $T {}
168 array_data_init! {
169 $T,
170 0 1 2 3 4 5 6 7 8 9
171 10 11 12 13 14 15 16 17 18 19
172 20 21 22 23 24 25 26 27 28 29
173 30 31 32
174 }
175 )*
176 #[cfg(test)]
177 mod data_init_tests {
178 use std::mem::{size_of, align_of};
179 use crate::DataInit;
180
181 #[test]
182 fn from_slice_alignment() {
183 let mut v = [0u8; 32];
184 $(
185 let (pre, _, _) = unsafe { v.align_to::<$T>() };
186 let pre_len = pre.len();
187
188 let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()];
189
190 let from_aligned = $T::from_slice(aligned_v);
191 assert_eq!(from_aligned, Some(&0));
192
193 let from_aligned_mut = $T::from_mut_slice(aligned_v);
194 assert_eq!(from_aligned_mut, Some(&mut 0));
195
196 for i in 1..size_of::<$T>() {
197 let begin = pre_len + i;
198 let end = begin + size_of::<$T>();
199 let unaligned_v = &mut v[begin..end];
200
201 let from_unaligned = $T::from_slice(unaligned_v);
202 if align_of::<$T>() != 1 {
203 assert_eq!(from_unaligned, None);
204 }
205
206 let from_unaligned_mut = $T::from_mut_slice(unaligned_v);
207 if align_of::<$T>() != 1 {
208 assert_eq!(from_unaligned_mut, None);
209 }
210 }
211 )*
212
213 }
214 }
215 };
216 }
217 data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
218
219 pub mod endian;
220 pub use crate::endian::*;
221
222 pub mod volatile_memory;
223 pub use crate::volatile_memory::*;
224
225 mod flexible_array;
226 pub use flexible_array::vec_with_array_field;
227 pub use flexible_array::FlexibleArray;
228 pub use flexible_array::FlexibleArrayWrapper;
229
230 mod sys;
231 pub use sys::create_iobuf;
232 pub use sys::IoBuf;
233 pub use sys::IoBufMut;
234