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}