Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/object-0.36.1/src/pod.rs
Line
Count
Source (jump to first uncovered line)
1
//! Tools for converting file format structures to and from bytes.
2
//!
3
//! This module should be replaced once rust provides safe transmutes.
4
5
// This module provides functions for both read and write features.
6
#![cfg_attr(
7
    not(all(feature = "read_core", feature = "write_core")),
8
    allow(dead_code)
9
)]
10
11
use core::{mem, result, slice};
12
13
type Result<T> = result::Result<T, ()>;
14
15
/// A trait for types that can safely be converted from and to byte slices.
16
///
17
/// # Safety
18
/// A type that is `Pod` must:
19
/// - be `#[repr(C)]` or `#[repr(transparent)]`
20
/// - have no invalid byte values
21
/// - have no padding
22
pub unsafe trait Pod: Copy + 'static {}
23
24
/// Cast the head of a byte slice to a `Pod` type.
25
///
26
/// Returns the type and the tail of the byte slice.
27
///
28
/// Returns an error if the byte slice is too short or the alignment is invalid.
29
#[inline]
30
0
pub fn from_bytes<T: Pod>(data: &[u8]) -> Result<(&T, &[u8])> {
31
0
    let size = mem::size_of::<T>();
32
0
    let tail = data.get(size..).ok_or(())?;
33
0
    let ptr = data.as_ptr();
34
0
    if (ptr as usize) % mem::align_of::<T>() != 0 {
35
0
        return Err(());
36
0
    }
37
0
    // Safety:
38
0
    // The alignment and size are checked by this function.
39
0
    // The Pod trait ensures the type is valid to cast from bytes.
40
0
    let val = unsafe { &*ptr.cast() };
41
0
    Ok((val, tail))
42
0
}
Unexecuted instantiation: object::pod::from_bytes::<object::elf::FileHeader64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::elf::NoteHeader32<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::elf::SectionHeader64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::elf::CompressionHeader64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::endian::U32Bytes<object::endian::BigEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::endian::U16Bytes<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageBaseRelocation>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageExportDirectory>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageImportDescriptor>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageResourceDataEntry>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageResourceDirectory>
Unexecuted instantiation: object::pod::from_bytes::<object::pe::ImageDelayloadDescriptor>
Unexecuted instantiation: object::pod::from_bytes::<u8>
43
44
/// Cast the head of a mutable byte slice to a `Pod` type.
45
///
46
/// Returns the type and the tail of the byte slice.
47
///
48
/// Returns an error if the byte slice is too short or the alignment is invalid.
49
#[inline]
50
0
pub fn from_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<(&mut T, &mut [u8])> {
51
0
    let size = mem::size_of::<T>();
52
0
    if size > data.len() {
53
0
        return Err(());
54
0
    }
55
0
    let (data, tail) = data.split_at_mut(size);
56
0
    let ptr = data.as_mut_ptr();
57
0
    if (ptr as usize) % mem::align_of::<T>() != 0 {
58
0
        return Err(());
59
0
    }
60
0
    // Safety:
61
0
    // The alignment and size are checked by this function.
62
0
    // The Pod trait ensures the type is valid to cast from bytes.
63
0
    let val = unsafe { &mut *ptr.cast() };
64
0
    Ok((val, tail))
65
0
}
66
67
/// Cast the head of a byte slice to a slice of a `Pod` type.
68
///
69
/// Returns the type slice and the tail of the byte slice.
70
///
71
/// Returns an error if the byte slice is too short or the alignment is invalid.
72
#[inline]
73
0
pub fn slice_from_bytes<T: Pod>(data: &[u8], count: usize) -> Result<(&[T], &[u8])> {
74
0
    let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
75
0
    let tail = data.get(size..).ok_or(())?;
76
0
    let ptr = data.as_ptr();
77
0
    if (ptr as usize) % mem::align_of::<T>() != 0 {
78
0
        return Err(());
79
0
    }
80
0
    // Safety:
81
0
    // The alignment and size are checked by this function.
82
0
    // The Pod trait ensures the type is valid to cast from bytes.
83
0
    let slice = unsafe { slice::from_raw_parts(ptr.cast(), count) };
84
0
    Ok((slice, tail))
85
0
}
Unexecuted instantiation: object::pod::slice_from_bytes::<object::elf::SectionHeader64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::elf::Sym64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U16Bytes<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::pe::ImageDataDirectory>
Unexecuted instantiation: object::pod::slice_from_bytes::<object::pe::ImageResourceDirectoryEntry>
86
87
/// Cast the head of a mutable byte slice to a slice of a `Pod` type.
88
///
89
/// Returns the type slice and the tail of the byte slice.
90
///
91
/// Returns an error if the byte slice is too short or the alignment is invalid.
92
#[inline]
93
0
pub fn slice_from_bytes_mut<T: Pod>(
94
0
    data: &mut [u8],
95
0
    count: usize,
96
0
) -> Result<(&mut [T], &mut [u8])> {
97
0
    let size = count.checked_mul(mem::size_of::<T>()).ok_or(())?;
98
0
    if size > data.len() {
99
0
        return Err(());
100
0
    }
101
0
    let (data, tail) = data.split_at_mut(size);
102
0
    let ptr = data.as_mut_ptr();
103
0
    if (ptr as usize) % mem::align_of::<T>() != 0 {
104
0
        return Err(());
105
0
    }
106
0
    // Safety:
107
0
    // The alignment and size are checked by this function.
108
0
    // The Pod trait ensures the type is valid to cast from bytes.
109
0
    let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), count) };
110
0
    Ok((slice, tail))
111
0
}
112
113
/// Cast all of a byte slice to a slice of a `Pod` type.
114
///
115
/// Returns the type slice.
116
///
117
/// Returns an error if the size of the byte slice is not an exact multiple
118
/// of the type size, or the alignment is invalid.
119
#[inline]
120
0
pub fn slice_from_all_bytes<T: Pod>(data: &[u8]) -> Result<&[T]> {
121
0
    let count = data.len() / mem::size_of::<T>();
122
0
    let (slice, tail) = slice_from_bytes(data, count)?;
123
0
    if !tail.is_empty() {
124
0
        return Err(());
125
0
    }
126
0
    Ok(slice)
127
0
}
Unexecuted instantiation: object::pod::slice_from_all_bytes::<object::elf::Sym64<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_all_bytes::<object::endian::U32Bytes<object::endian::LittleEndian>>
Unexecuted instantiation: object::pod::slice_from_all_bytes::<_>
128
129
/// Cast all of a byte slice to a slice of a `Pod` type.
130
///
131
/// Returns the type slice.
132
///
133
/// Returns an error if the size of the byte slice is not an exact multiple
134
/// of the type size, or the alignment is invalid.
135
#[inline]
136
0
pub fn slice_from_all_bytes_mut<T: Pod>(data: &mut [u8]) -> Result<&mut [T]> {
137
0
    let count = data.len() / mem::size_of::<T>();
138
0
    let (slice, tail) = slice_from_bytes_mut(data, count)?;
139
0
    if !tail.is_empty() {
140
0
        return Err(());
141
0
    }
142
0
    Ok(slice)
143
0
}
144
145
/// Cast a `Pod` type to a byte slice.
146
#[inline]
147
0
pub fn bytes_of<T: Pod>(val: &T) -> &[u8] {
148
0
    let size = mem::size_of::<T>();
149
0
    // Safety:
150
0
    // Any alignment is allowed.
151
0
    // The size is determined in this function.
152
0
    // The Pod trait ensures the type is valid to cast to bytes.
153
0
    unsafe { slice::from_raw_parts(slice::from_ref(val).as_ptr().cast(), size) }
154
0
}
155
156
/// Cast a `Pod` type to a mutable byte slice.
157
#[inline]
158
0
pub fn bytes_of_mut<T: Pod>(val: &mut T) -> &mut [u8] {
159
0
    let size = mem::size_of::<T>();
160
0
    // Safety:
161
0
    // Any alignment is allowed.
162
0
    // The size is determined in this function.
163
0
    // The Pod trait ensures the type is valid to cast to bytes.
164
0
    unsafe { slice::from_raw_parts_mut(slice::from_mut(val).as_mut_ptr().cast(), size) }
165
0
}
166
167
/// Cast a slice of a `Pod` type to a byte slice.
168
#[inline]
169
0
pub fn bytes_of_slice<T: Pod>(val: &[T]) -> &[u8] {
170
0
    let size = val.len().wrapping_mul(mem::size_of::<T>());
171
0
    // Safety:
172
0
    // Any alignment is allowed.
173
0
    // The size is determined in this function.
174
0
    // The Pod trait ensures the type is valid to cast to bytes.
175
0
    unsafe { slice::from_raw_parts(val.as_ptr().cast(), size) }
176
0
}
177
178
/// Cast a slice of a `Pod` type to a mutable byte slice.
179
#[inline]
180
0
pub fn bytes_of_slice_mut<T: Pod>(val: &mut [T]) -> &mut [u8] {
181
0
    let size = val.len().wrapping_mul(mem::size_of::<T>());
182
0
    // Safety:
183
0
    // Any alignment is allowed.
184
0
    // The size is determined in this function.
185
0
    // The Pod trait ensures the type is valid to cast to bytes.
186
0
    unsafe { slice::from_raw_parts_mut(val.as_mut_ptr().cast(), size) }
187
0
}
188
189
macro_rules! unsafe_impl_pod {
190
    ($($struct_name:ident),+ $(,)?) => {
191
        $(
192
            unsafe impl Pod for $struct_name { }
193
        )+
194
    }
195
}
196
197
unsafe_impl_pod!(u8, u16, u32, u64);
198
199
unsafe impl<const N: usize, T: Pod> Pod for [T; N] {}
200
201
#[cfg(test)]
202
mod tests {
203
    use super::*;
204
205
    #[test]
206
    fn single() {
207
        let x = u32::to_be(0x0123_4567);
208
        let mut x_mut = x;
209
        let bytes = bytes_of(&x);
210
        let bytes_mut = bytes_of_mut(&mut x_mut);
211
        assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67]);
212
        assert_eq!(bytes, bytes_mut);
213
214
        let x16 = [u16::to_be(0x0123), u16::to_be(0x4567)];
215
216
        let (y, tail) = from_bytes::<u32>(bytes).unwrap();
217
        let (y_mut, tail_mut) = from_bytes_mut::<u32>(bytes_mut).unwrap();
218
        assert_eq!(*y, x);
219
        assert_eq!(y, y_mut);
220
        assert_eq!(tail, &[]);
221
        assert_eq!(tail, tail_mut);
222
223
        let (y, tail) = from_bytes::<u16>(bytes).unwrap();
224
        let (y_mut, tail_mut) = from_bytes_mut::<u16>(bytes_mut).unwrap();
225
        assert_eq!(*y, x16[0]);
226
        assert_eq!(y, y_mut);
227
        assert_eq!(tail, &bytes[2..]);
228
        assert_eq!(tail, tail_mut);
229
230
        let (y, tail) = from_bytes::<u16>(&bytes[2..]).unwrap();
231
        let (y_mut, tail_mut) = from_bytes_mut::<u16>(&mut bytes_mut[2..]).unwrap();
232
        assert_eq!(*y, x16[1]);
233
        assert_eq!(y, y_mut);
234
        assert_eq!(tail, &[]);
235
        assert_eq!(tail, tail_mut);
236
237
        assert_eq!(from_bytes::<u16>(&bytes[1..]), Err(()));
238
        assert_eq!(from_bytes::<u16>(&bytes[3..]), Err(()));
239
        assert_eq!(from_bytes::<u16>(&bytes[4..]), Err(()));
240
        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[1..]), Err(()));
241
        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[3..]), Err(()));
242
        assert_eq!(from_bytes_mut::<u16>(&mut bytes_mut[4..]), Err(()));
243
    }
244
245
    #[test]
246
    fn slice() {
247
        let x = [
248
            u16::to_be(0x0123),
249
            u16::to_be(0x4567),
250
            u16::to_be(0x89ab),
251
            u16::to_be(0xcdef),
252
        ];
253
        let mut x_mut = x;
254
255
        let bytes = bytes_of_slice(&x);
256
        let bytes_mut = bytes_of_slice_mut(&mut x_mut);
257
        assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
258
        assert_eq!(bytes, bytes_mut);
259
260
        let (y, tail) = slice_from_bytes::<u16>(bytes, 4).unwrap();
261
        let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(bytes_mut, 4).unwrap();
262
        assert_eq!(y, x);
263
        assert_eq!(y, y_mut);
264
        assert_eq!(tail, &[]);
265
        assert_eq!(tail, tail_mut);
266
267
        let (y, tail) = slice_from_bytes::<u16>(&bytes[2..], 2).unwrap();
268
        let (y_mut, tail_mut) = slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 2).unwrap();
269
        assert_eq!(y, &x[1..3]);
270
        assert_eq!(y, y_mut);
271
        assert_eq!(tail, &bytes[6..]);
272
        assert_eq!(tail, tail_mut);
273
274
        assert_eq!(slice_from_bytes::<u16>(bytes, 5), Err(()));
275
        assert_eq!(slice_from_bytes::<u16>(&bytes[2..], 4), Err(()));
276
        assert_eq!(slice_from_bytes::<u16>(&bytes[1..], 2), Err(()));
277
        assert_eq!(slice_from_bytes_mut::<u16>(bytes_mut, 5), Err(()));
278
        assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[2..], 4), Err(()));
279
        assert_eq!(slice_from_bytes_mut::<u16>(&mut bytes_mut[1..], 2), Err(()));
280
    }
281
}