• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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