virtio_driver/util/bytevalued.rs
1// Copyright (C) 2022 Red Hat, Inc. All rights reserved.
2//
3// Copyright 2017 The Chromium OS Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE.crosvm file.
6
7use std::io;
8use std::mem::{size_of, MaybeUninit};
9use std::slice::{from_raw_parts, from_raw_parts_mut};
10
11/// Types for which it is safe to initialize from raw data.
12///
13///
14/// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
15///
16/// # Safety
17/// A type `T` is `ByteValued` if it can be initialized by reading its contents from a byte array.
18/// This is generally true for all plain-old-data structs. It is notably not true for any type
19/// that includes a reference.
20///
21/// It is unsafe for `T` to be `ByteValued` if `T` contains implicit padding. (LLVM considers access
22/// to implicit padding to be undefined behavior, which can cause UB when working with `T`.
23/// For details on structure padding in Rust, see
24/// <https://doc.rust-lang.org/reference/type-layout.html#the-c-representation>.
25pub unsafe trait ByteValued: Copy + Send + Sync {
26 /// Converts a slice of raw data into a reference of `Self`.
27 ///
28 /// The value of `data` is not copied. Instead a reference is made from the given slice. The
29 /// value of `Self` will depend on the representation of the type in memory, and may change in
30 /// an unstable fashion.
31 ///
32 /// This will return `None` if the length of data does not match the size of `Self`, or if the
33 /// data is not aligned for the type of `Self`.
34 fn from_slice(data: &[u8]) -> Option<&Self> {
35 // Early out to avoid an unneeded `align_to` call.
36 if data.len() != size_of::<Self>() {
37 return None;
38 }
39
40 // Safe because the ByteValued trait asserts any data is valid for this type, and we ensured
41 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
42 // we don't have any unaligned references. This aliases a pointer, but because the pointer
43 // is from a const slice reference, there are no mutable aliases. Finally, the reference
44 // returned can not outlive data because they have equal implicit lifetime constraints.
45 match unsafe { data.align_to::<Self>() } {
46 ([], [mid], []) => Some(mid),
47 _ => None,
48 }
49 }
50
51 /// Converts a mutable slice of raw data into a mutable reference of `Self`.
52 ///
53 /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
54 /// reference are immediately reflected in `data`. The value of the returned `Self` will depend
55 /// on the representation of the type in memory, and may change in an unstable fashion.
56 ///
57 /// This will return `None` if the length of data does not match the size of `Self`, or if the
58 /// data is not aligned for the type of `Self`.
59 fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
60 // Early out to avoid an unneeded `align_to_mut` call.
61 if data.len() != size_of::<Self>() {
62 return None;
63 }
64
65 // Safe because the ByteValued trait asserts any data is valid for this type, and we ensured
66 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
67 // we don't have any unaligned references. This aliases a pointer, but because the pointer
68 // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
69 // reference returned can not outlive data because they have equal implicit lifetime
70 // constraints.
71 match unsafe { data.align_to_mut::<Self>() } {
72 ([], [mid], []) => Some(mid),
73 _ => None,
74 }
75 }
76
77 /// Creates an instance of `Self` by copying raw data from an io::Read stream.
78 fn from_reader<R: io::Read>(mut read: R) -> io::Result<Self> {
79 // Allocate on the stack via `MaybeUninit` to ensure proper alignment.
80 let mut out = MaybeUninit::zeroed();
81
82 // Safe because the pointer is valid and points to `size_of::<Self>()` bytes of zeroes,
83 // which is a properly initialized value for `u8`.
84 let buf = unsafe { from_raw_parts_mut(out.as_mut_ptr() as *mut u8, size_of::<Self>()) };
85 read.read_exact(buf)?;
86
87 // Safe because any bit pattern is considered a valid value for `Self`.
88 Ok(unsafe { out.assume_init() })
89 }
90
91 /// Converts a reference to `self` into a slice of bytes.
92 ///
93 /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
94 /// The value of bytes in the returned slice will depend on the representation of the type in
95 /// memory, and may change in an unstable fashion.
96 fn as_slice(&self) -> &[u8] {
97 // Safe because the entire size of self is accessible as bytes because the trait guarantees
98 // it. The lifetime of the returned slice is the same as the passed reference, so that no
99 // dangling pointers will result from this pointer alias.
100 unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
101 }
102
103 /// Converts a mutable reference to `self` into a mutable slice of bytes.
104 ///
105 /// Because the slice is made from a reference to `self`, mutations to the returned slice are
106 /// immediately reflected in `self`. The value of bytes in the returned slice will depend on
107 /// the representation of the type in memory, and may change in an unstable fashion.
108 fn as_mut_slice(&mut self) -> &mut [u8] {
109 // Safe because the entire size of self is accessible as bytes because the trait guarantees
110 // it. The trait also guarantees that any combination of bytes is valid for this type, so
111 // modifying them in the form of a byte slice is valid. The lifetime of the returned slice
112 // is the same as the passed reference, so that no dangling pointers will result from this
113 // pointer alias. Although this does alias a mutable pointer, we do so by exclusively
114 // borrowing the given mutable reference.
115 unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
116 }
117}