• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
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::{align_of, size_of};
7 use std::slice::{from_raw_parts, from_raw_parts_mut};
8 
9 /// Types for which it is safe to initialize from raw data.
10 ///
11 ///
12 /// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
13 ///
14 /// # Safety
15 /// A type `T` is `DataInit` if it can be initialized by reading its contents from a byte array.
16 /// This is generally true for all plain-old-data structs.  It is notably not true for any type
17 /// that includes a reference.
18 ///
19 /// It is unsafe for `T` to be `DataInit` if `T` contains implicit padding. (LLVM considers access
20 /// to implicit padding to be undefined behavior, which can cause UB when working with `T`.
21 /// For details on structure padding in Rust, see
22 /// https://doc.rust-lang.org/reference/type-layout.html#the-c-representation
23 pub unsafe trait DataInit: Copy + Send + Sync {
24     /// Converts a slice of raw data into a reference of `Self`.
25     ///
26     /// The value of `data` is not copied. Instead a reference is made from the given slice. The
27     /// value of `Self` will depend on the representation of the type in memory, and may change in
28     /// an unstable fashion.
29     ///
30     /// This will return `None` if the length of data does not match the size of `Self`, or if the
31     /// data is not aligned for the type of `Self`.
from_slice(data: &[u8]) -> Option<&Self>32     fn from_slice(data: &[u8]) -> Option<&Self> {
33         // Early out to avoid an unneeded `align_to` call.
34         if data.len() != size_of::<Self>() {
35             return None;
36         }
37 
38         // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
39         // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
40         // we don't have any unaligned references. This aliases a pointer, but because the pointer
41         // is from a const slice reference, there are no mutable aliases. Finally, the reference
42         // returned can not outlive data because they have equal implicit lifetime constraints.
43         match unsafe { data.align_to::<Self>() } {
44             ([], [mid], []) => Some(mid),
45             _ => None,
46         }
47     }
48 
49     /// Converts a mutable slice of raw data into a mutable reference of `Self`.
50     ///
51     /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
52     /// reference are immediately reflected in `data`. The value of the returned `Self` will depend
53     /// on the representation of the type in memory, and may change in an unstable fashion.
54     ///
55     /// This will return `None` if the length of data does not match the size of `Self`, or if the
56     /// data is not aligned for the type of `Self`.
from_mut_slice(data: &mut [u8]) -> Option<&mut Self>57     fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
58         // Early out to avoid an unneeded `align_to_mut` call.
59         if data.len() != size_of::<Self>() {
60             return None;
61         }
62 
63         // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
64         // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
65         // we don't have any unaligned references. This aliases a pointer, but because the pointer
66         // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
67         // reference returned can not outlive data because they have equal implicit lifetime
68         // constraints.
69         match unsafe { data.align_to_mut::<Self>() } {
70             ([], [mid], []) => Some(mid),
71             _ => None,
72         }
73     }
74 
75     /// 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>76     fn from_reader<R: io::Read>(mut read: R) -> io::Result<Self> {
77         // Allocate a Vec<u8> with enough extra space for the worst-case alignment offset.
78         let mut data = vec![0u8; size_of::<Self>() + align_of::<Self>()];
79 
80         // Get a u8 slice within data with sufficient alignment for Self.
81         let align_offset = data.as_ptr().align_offset(align_of::<Self>());
82         let mut aligned_data = &mut data[align_offset..align_offset + size_of::<Self>()];
83 
84         read.read_exact(&mut aligned_data)?;
85         match Self::from_slice(&aligned_data) {
86             Some(obj) => Ok(*obj),
87             None => Err(io::Error::new(
88                 io::ErrorKind::InvalidData,
89                 "from_slice failed",
90             )),
91         }
92     }
93 
94     /// Converts a reference to `self` into a slice of bytes.
95     ///
96     /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
97     /// The value of bytes in the returned slice will depend on the representation of the type in
98     /// memory, and may change in an unstable fashion.
as_slice(&self) -> &[u8]99     fn as_slice(&self) -> &[u8] {
100         // Safe because the entire size of self is accessible as bytes because the trait guarantees
101         // it. The lifetime of the returned slice is the same as the passed reference, so that no
102         // dangling pointers will result from this pointer alias.
103         unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
104     }
105 
106     /// Converts a mutable reference to `self` into a mutable slice of bytes.
107     ///
108     /// Because the slice is made from a reference to `self`, mutations to the returned slice are
109     /// immediately reflected in `self`. The value of bytes in the returned slice will depend on
110     /// the representation of the type in memory, and may change in an unstable fashion.
as_mut_slice(&mut self) -> &mut [u8]111     fn as_mut_slice(&mut self) -> &mut [u8] {
112         // Safe because the entire size of self is accessible as bytes because the trait guarantees
113         // it. The trait also guarantees that any combination of bytes is valid for this type, so
114         // modifying them in the form of a byte slice is valid. The lifetime of the returned slice
115         // is the same as the passed reference, so that no dangling pointers will result from this
116         // pointer alias. Although this does alias a mutable pointer, we do so by exclusively
117         // borrowing the given mutable reference.
118         unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
119     }
120 }
121 
122 // All intrinsic types and arays of intrinsic types are DataInit.  They are just numbers.
123 macro_rules! array_data_init {
124     ($T:ty, $($N:expr)+) => {
125         $(
126             unsafe impl DataInit for [$T; $N] {}
127         )+
128     }
129 }
130 macro_rules! data_init_type {
131     ($($T:ident),*) => {
132         $(
133             unsafe impl DataInit for $T {}
134             array_data_init! {
135                 $T,
136                 0  1  2  3  4  5  6  7  8  9
137                 10 11 12 13 14 15 16 17 18 19
138                 20 21 22 23 24 25 26 27 28 29
139                 30 31 32
140             }
141         )*
142         #[cfg(test)]
143         mod data_init_tests {
144             use std::mem::{size_of, align_of};
145             use crate::DataInit;
146 
147             #[test]
148             fn from_slice_alignment() {
149                 let mut v = [0u8; 32];
150                 $(
151                     let (pre, _, _) = unsafe { v.align_to::<$T>() };
152                     let pre_len = pre.len();
153 
154                     let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()];
155 
156                     let from_aligned = $T::from_slice(aligned_v);
157                     assert_eq!(from_aligned, Some(&0));
158 
159                     let from_aligned_mut = $T::from_mut_slice(aligned_v);
160                     assert_eq!(from_aligned_mut, Some(&mut 0));
161 
162                     for i in 1..size_of::<$T>() {
163                         let begin = pre_len + i;
164                         let end = begin + size_of::<$T>();
165                         let unaligned_v = &mut v[begin..end];
166 
167                         let from_unaligned = $T::from_slice(unaligned_v);
168                         if align_of::<$T>() != 1 {
169                             assert_eq!(from_unaligned, None);
170                         }
171 
172                         let from_unaligned_mut = $T::from_mut_slice(unaligned_v);
173                         if align_of::<$T>() != 1 {
174                             assert_eq!(from_unaligned_mut, None);
175                         }
176                     }
177                 )*
178 
179             }
180         }
181     };
182 }
183 data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
184 
185 pub mod endian;
186 pub use crate::endian::*;
187 
188 pub mod volatile_memory;
189 pub use crate::volatile_memory::*;
190 
191 mod flexible_array;
192 pub use flexible_array::{vec_with_array_field, FlexibleArray, FlexibleArrayWrapper};
193 
194 mod sys;
195 pub use sys::IoBufMut;
196