1*d289c2baSAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*d289c2baSAndroid Build Coastguard Worker //
3*d289c2baSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*d289c2baSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*d289c2baSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*d289c2baSAndroid Build Coastguard Worker //
7*d289c2baSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*d289c2baSAndroid Build Coastguard Worker //
9*d289c2baSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*d289c2baSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*d289c2baSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d289c2baSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*d289c2baSAndroid Build Coastguard Worker // limitations under the License.
14*d289c2baSAndroid Build Coastguard Worker
15*d289c2baSAndroid Build Coastguard Worker //! Descriptor extraction and handling.
16*d289c2baSAndroid Build Coastguard Worker //!
17*d289c2baSAndroid Build Coastguard Worker //! Descriptors are information encoded into vbmeta images which can be
18*d289c2baSAndroid Build Coastguard Worker //! extracted from the resulting data after performing verification.
19*d289c2baSAndroid Build Coastguard Worker
20*d289c2baSAndroid Build Coastguard Worker extern crate alloc;
21*d289c2baSAndroid Build Coastguard Worker
22*d289c2baSAndroid Build Coastguard Worker mod chain;
23*d289c2baSAndroid Build Coastguard Worker mod commandline;
24*d289c2baSAndroid Build Coastguard Worker mod hash;
25*d289c2baSAndroid Build Coastguard Worker mod hashtree;
26*d289c2baSAndroid Build Coastguard Worker mod property;
27*d289c2baSAndroid Build Coastguard Worker mod util;
28*d289c2baSAndroid Build Coastguard Worker
29*d289c2baSAndroid Build Coastguard Worker use crate::VbmetaData;
30*d289c2baSAndroid Build Coastguard Worker use alloc::vec::Vec;
31*d289c2baSAndroid Build Coastguard Worker use avb_bindgen::{
32*d289c2baSAndroid Build Coastguard Worker avb_descriptor_foreach, avb_descriptor_validate_and_byteswap, AvbDescriptor, AvbDescriptorTag,
33*d289c2baSAndroid Build Coastguard Worker };
34*d289c2baSAndroid Build Coastguard Worker use core::{
35*d289c2baSAndroid Build Coastguard Worker ffi::{c_void, FromBytesUntilNulError},
36*d289c2baSAndroid Build Coastguard Worker mem::size_of,
37*d289c2baSAndroid Build Coastguard Worker slice,
38*d289c2baSAndroid Build Coastguard Worker str::Utf8Error,
39*d289c2baSAndroid Build Coastguard Worker };
40*d289c2baSAndroid Build Coastguard Worker
41*d289c2baSAndroid Build Coastguard Worker pub use chain::{ChainPartitionDescriptor, ChainPartitionDescriptorFlags};
42*d289c2baSAndroid Build Coastguard Worker pub use commandline::{KernelCommandlineDescriptor, KernelCommandlineDescriptorFlags};
43*d289c2baSAndroid Build Coastguard Worker pub use hash::{HashDescriptor, HashDescriptorFlags};
44*d289c2baSAndroid Build Coastguard Worker pub use hashtree::{HashtreeDescriptor, HashtreeDescriptorFlags};
45*d289c2baSAndroid Build Coastguard Worker pub use property::PropertyDescriptor;
46*d289c2baSAndroid Build Coastguard Worker
47*d289c2baSAndroid Build Coastguard Worker /// A single descriptor.
48*d289c2baSAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq)]
49*d289c2baSAndroid Build Coastguard Worker pub enum Descriptor<'a> {
50*d289c2baSAndroid Build Coastguard Worker /// Wraps `AvbPropertyDescriptor`.
51*d289c2baSAndroid Build Coastguard Worker Property(PropertyDescriptor<'a>),
52*d289c2baSAndroid Build Coastguard Worker /// Wraps `AvbHashtreeDescriptor`.
53*d289c2baSAndroid Build Coastguard Worker Hashtree(HashtreeDescriptor<'a>),
54*d289c2baSAndroid Build Coastguard Worker /// Wraps `AvbHashDescriptor`.
55*d289c2baSAndroid Build Coastguard Worker Hash(HashDescriptor<'a>),
56*d289c2baSAndroid Build Coastguard Worker /// Wraps `AvbKernelCmdlineDescriptor`.
57*d289c2baSAndroid Build Coastguard Worker KernelCommandline(KernelCommandlineDescriptor<'a>),
58*d289c2baSAndroid Build Coastguard Worker /// Wraps `AvbChainPartitionDescriptor`.
59*d289c2baSAndroid Build Coastguard Worker ChainPartition(ChainPartitionDescriptor<'a>),
60*d289c2baSAndroid Build Coastguard Worker /// Unknown descriptor type.
61*d289c2baSAndroid Build Coastguard Worker Unknown(&'a [u8]),
62*d289c2baSAndroid Build Coastguard Worker }
63*d289c2baSAndroid Build Coastguard Worker
64*d289c2baSAndroid Build Coastguard Worker /// Possible errors when extracting descriptors.
65*d289c2baSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq)]
66*d289c2baSAndroid Build Coastguard Worker pub enum DescriptorError {
67*d289c2baSAndroid Build Coastguard Worker /// libavb rejected the descriptor header.
68*d289c2baSAndroid Build Coastguard Worker InvalidHeader,
69*d289c2baSAndroid Build Coastguard Worker /// A value in the descriptor was invalid.
70*d289c2baSAndroid Build Coastguard Worker InvalidValue,
71*d289c2baSAndroid Build Coastguard Worker /// The descriptor claimed to be larger than the available data.
72*d289c2baSAndroid Build Coastguard Worker InvalidSize,
73*d289c2baSAndroid Build Coastguard Worker /// A field that was supposed to be valid UTF-8 was not.
74*d289c2baSAndroid Build Coastguard Worker InvalidUtf8,
75*d289c2baSAndroid Build Coastguard Worker /// Descriptor contents don't match what we expect.
76*d289c2baSAndroid Build Coastguard Worker InvalidContents,
77*d289c2baSAndroid Build Coastguard Worker }
78*d289c2baSAndroid Build Coastguard Worker
79*d289c2baSAndroid Build Coastguard Worker impl From<Utf8Error> for DescriptorError {
from(_: Utf8Error) -> Self80*d289c2baSAndroid Build Coastguard Worker fn from(_: Utf8Error) -> Self {
81*d289c2baSAndroid Build Coastguard Worker Self::InvalidUtf8
82*d289c2baSAndroid Build Coastguard Worker }
83*d289c2baSAndroid Build Coastguard Worker }
84*d289c2baSAndroid Build Coastguard Worker
85*d289c2baSAndroid Build Coastguard Worker impl From<FromBytesUntilNulError> for DescriptorError {
from(_: FromBytesUntilNulError) -> Self86*d289c2baSAndroid Build Coastguard Worker fn from(_: FromBytesUntilNulError) -> Self {
87*d289c2baSAndroid Build Coastguard Worker Self::InvalidContents
88*d289c2baSAndroid Build Coastguard Worker }
89*d289c2baSAndroid Build Coastguard Worker }
90*d289c2baSAndroid Build Coastguard Worker
91*d289c2baSAndroid Build Coastguard Worker /// `Result` type for `DescriptorError` errors.
92*d289c2baSAndroid Build Coastguard Worker pub type DescriptorResult<T> = Result<T, DescriptorError>;
93*d289c2baSAndroid Build Coastguard Worker
94*d289c2baSAndroid Build Coastguard Worker impl<'a> Descriptor<'a> {
95*d289c2baSAndroid Build Coastguard Worker /// Extracts the fully-typed descriptor from the generic `AvbDescriptor` header.
96*d289c2baSAndroid Build Coastguard Worker ///
97*d289c2baSAndroid Build Coastguard Worker /// # Arguments
98*d289c2baSAndroid Build Coastguard Worker /// * `raw_descriptor`: the raw `AvbDescriptor` pointing into the vbmeta image.
99*d289c2baSAndroid Build Coastguard Worker ///
100*d289c2baSAndroid Build Coastguard Worker /// # Returns
101*d289c2baSAndroid Build Coastguard Worker /// The fully-typed `Descriptor`, or `DescriptorError` if parsing the descriptor failed.
102*d289c2baSAndroid Build Coastguard Worker ///
103*d289c2baSAndroid Build Coastguard Worker /// # Safety
104*d289c2baSAndroid Build Coastguard Worker /// `raw_descriptor` must point to a valid `AvbDescriptor`, including the `num_bytes_following`
105*d289c2baSAndroid Build Coastguard Worker /// data contents, that lives at least as long as `'a`.
new(raw_descriptor: *const AvbDescriptor) -> DescriptorResult<Self>106*d289c2baSAndroid Build Coastguard Worker unsafe fn new(raw_descriptor: *const AvbDescriptor) -> DescriptorResult<Self> {
107*d289c2baSAndroid Build Coastguard Worker // Transform header to host-endian.
108*d289c2baSAndroid Build Coastguard Worker let mut descriptor = AvbDescriptor {
109*d289c2baSAndroid Build Coastguard Worker tag: 0,
110*d289c2baSAndroid Build Coastguard Worker num_bytes_following: 0,
111*d289c2baSAndroid Build Coastguard Worker };
112*d289c2baSAndroid Build Coastguard Worker // SAFETY: both args point to valid `AvbDescriptor` objects.
113*d289c2baSAndroid Build Coastguard Worker if !unsafe { avb_descriptor_validate_and_byteswap(raw_descriptor, &mut descriptor) } {
114*d289c2baSAndroid Build Coastguard Worker return Err(DescriptorError::InvalidHeader);
115*d289c2baSAndroid Build Coastguard Worker }
116*d289c2baSAndroid Build Coastguard Worker
117*d289c2baSAndroid Build Coastguard Worker // Extract the descriptor header and contents bytes. The descriptor sub-type headers
118*d289c2baSAndroid Build Coastguard Worker // include the top-level header as the first member, so we need to grab the entire
119*d289c2baSAndroid Build Coastguard Worker // descriptor including the top-level header.
120*d289c2baSAndroid Build Coastguard Worker let num_bytes_following = descriptor
121*d289c2baSAndroid Build Coastguard Worker .num_bytes_following
122*d289c2baSAndroid Build Coastguard Worker .try_into()
123*d289c2baSAndroid Build Coastguard Worker .map_err(|_| DescriptorError::InvalidValue)?;
124*d289c2baSAndroid Build Coastguard Worker let total_size = size_of::<AvbDescriptor>()
125*d289c2baSAndroid Build Coastguard Worker .checked_add(num_bytes_following)
126*d289c2baSAndroid Build Coastguard Worker .ok_or(DescriptorError::InvalidValue)?;
127*d289c2baSAndroid Build Coastguard Worker
128*d289c2baSAndroid Build Coastguard Worker // SAFETY: `raw_descriptor` points to the header plus `num_bytes_following` bytes.
129*d289c2baSAndroid Build Coastguard Worker let contents = unsafe { slice::from_raw_parts(raw_descriptor as *const u8, total_size) };
130*d289c2baSAndroid Build Coastguard Worker
131*d289c2baSAndroid Build Coastguard Worker match descriptor.tag.try_into() {
132*d289c2baSAndroid Build Coastguard Worker Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_PROPERTY) => {
133*d289c2baSAndroid Build Coastguard Worker Ok(Descriptor::Property(PropertyDescriptor::new(contents)?))
134*d289c2baSAndroid Build Coastguard Worker }
135*d289c2baSAndroid Build Coastguard Worker Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_HASHTREE) => {
136*d289c2baSAndroid Build Coastguard Worker Ok(Descriptor::Hashtree(HashtreeDescriptor::new(contents)?))
137*d289c2baSAndroid Build Coastguard Worker }
138*d289c2baSAndroid Build Coastguard Worker Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_HASH) => {
139*d289c2baSAndroid Build Coastguard Worker Ok(Descriptor::Hash(HashDescriptor::new(contents)?))
140*d289c2baSAndroid Build Coastguard Worker }
141*d289c2baSAndroid Build Coastguard Worker Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) => Ok(
142*d289c2baSAndroid Build Coastguard Worker Descriptor::KernelCommandline(KernelCommandlineDescriptor::new(contents)?),
143*d289c2baSAndroid Build Coastguard Worker ),
144*d289c2baSAndroid Build Coastguard Worker Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) => Ok(
145*d289c2baSAndroid Build Coastguard Worker Descriptor::ChainPartition(ChainPartitionDescriptor::new(contents)?),
146*d289c2baSAndroid Build Coastguard Worker ),
147*d289c2baSAndroid Build Coastguard Worker _ => Ok(Descriptor::Unknown(contents)),
148*d289c2baSAndroid Build Coastguard Worker }
149*d289c2baSAndroid Build Coastguard Worker }
150*d289c2baSAndroid Build Coastguard Worker }
151*d289c2baSAndroid Build Coastguard Worker
152*d289c2baSAndroid Build Coastguard Worker /// Returns a vector of descriptors extracted from the given vbmeta image.
153*d289c2baSAndroid Build Coastguard Worker ///
154*d289c2baSAndroid Build Coastguard Worker /// # Arguments
155*d289c2baSAndroid Build Coastguard Worker /// * `vbmeta`: the `VbmetaData` object to extract descriptors from.
156*d289c2baSAndroid Build Coastguard Worker ///
157*d289c2baSAndroid Build Coastguard Worker /// # Returns
158*d289c2baSAndroid Build Coastguard Worker /// The descriptors, or `DescriptorError` if any error occurred.
159*d289c2baSAndroid Build Coastguard Worker ///
160*d289c2baSAndroid Build Coastguard Worker /// # Safety
161*d289c2baSAndroid Build Coastguard Worker /// `vbmeta` must have been validated by `slot_verify()`.
get_descriptors(vbmeta: &VbmetaData) -> DescriptorResult<Vec<Descriptor>>162*d289c2baSAndroid Build Coastguard Worker pub(crate) unsafe fn get_descriptors(vbmeta: &VbmetaData) -> DescriptorResult<Vec<Descriptor>> {
163*d289c2baSAndroid Build Coastguard Worker let mut result = Ok(Vec::new());
164*d289c2baSAndroid Build Coastguard Worker
165*d289c2baSAndroid Build Coastguard Worker // Use `avb_descriptor_foreach()` to grab all the descriptor pointers in `vmbeta.data()`.
166*d289c2baSAndroid Build Coastguard Worker // This implementation processes all the descriptors immediately, so that any error is
167*d289c2baSAndroid Build Coastguard Worker // detected here and working with descriptors can be error-free.
168*d289c2baSAndroid Build Coastguard Worker //
169*d289c2baSAndroid Build Coastguard Worker // SAFETY:
170*d289c2baSAndroid Build Coastguard Worker // * the caller ensures that `vbmeta` has been validated by `slot_verify()`, which satisfies
171*d289c2baSAndroid Build Coastguard Worker // the libavb `avb_vbmeta_image_verify()` requirement.
172*d289c2baSAndroid Build Coastguard Worker // * `avb_descriptor_foreach()` ensures the validity of each descriptor pointer passed to
173*d289c2baSAndroid Build Coastguard Worker // the `fill_descriptors_vec()` callback.
174*d289c2baSAndroid Build Coastguard Worker // * our lifetimes guarantee that the raw descriptor data in `vbmeta` will remain unchanged for
175*d289c2baSAndroid Build Coastguard Worker // the lifetime of the returned `Descriptor` objects.
176*d289c2baSAndroid Build Coastguard Worker // * the `user_data` param is a valid `DescriptorResult<Vec<Descriptor>>` with no other
177*d289c2baSAndroid Build Coastguard Worker // concurrent access.
178*d289c2baSAndroid Build Coastguard Worker unsafe {
179*d289c2baSAndroid Build Coastguard Worker // We can ignore the return value of this function since we use the passed-in `result`
180*d289c2baSAndroid Build Coastguard Worker // to convey success/failure as well as more detailed error info.
181*d289c2baSAndroid Build Coastguard Worker avb_descriptor_foreach(
182*d289c2baSAndroid Build Coastguard Worker vbmeta.data().as_ptr(),
183*d289c2baSAndroid Build Coastguard Worker vbmeta.data().len(),
184*d289c2baSAndroid Build Coastguard Worker Some(fill_descriptors_vec),
185*d289c2baSAndroid Build Coastguard Worker &mut result as *mut _ as *mut c_void,
186*d289c2baSAndroid Build Coastguard Worker );
187*d289c2baSAndroid Build Coastguard Worker }
188*d289c2baSAndroid Build Coastguard Worker
189*d289c2baSAndroid Build Coastguard Worker result
190*d289c2baSAndroid Build Coastguard Worker }
191*d289c2baSAndroid Build Coastguard Worker
192*d289c2baSAndroid Build Coastguard Worker /// Adds the given descriptor to the `Vec` pointed to by `user_data`.
193*d289c2baSAndroid Build Coastguard Worker ///
194*d289c2baSAndroid Build Coastguard Worker /// Serves as a C callback for use with `avb_descriptor_foreach()`.
195*d289c2baSAndroid Build Coastguard Worker ///
196*d289c2baSAndroid Build Coastguard Worker /// # Returns
197*d289c2baSAndroid Build Coastguard Worker /// True on success, false on failure (which will stop iteration early).
198*d289c2baSAndroid Build Coastguard Worker ///
199*d289c2baSAndroid Build Coastguard Worker /// # Safety
200*d289c2baSAndroid Build Coastguard Worker /// * `descriptor` must point to a valid `AvbDescriptor`, including the `num_bytes_following`
201*d289c2baSAndroid Build Coastguard Worker /// data contents, which remains valid and unmodified for the lifetime of the `Descriptor` objects
202*d289c2baSAndroid Build Coastguard Worker /// in `user_data`.
203*d289c2baSAndroid Build Coastguard Worker /// * `user_data` must point to a valid `DescriptorResult<Vec<Descriptor>>` with no other concurrent
204*d289c2baSAndroid Build Coastguard Worker /// access.
fill_descriptors_vec( descriptor: *const AvbDescriptor, user_data: *mut c_void, ) -> bool205*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn fill_descriptors_vec(
206*d289c2baSAndroid Build Coastguard Worker descriptor: *const AvbDescriptor,
207*d289c2baSAndroid Build Coastguard Worker user_data: *mut c_void,
208*d289c2baSAndroid Build Coastguard Worker ) -> bool {
209*d289c2baSAndroid Build Coastguard Worker // SAFETY: `user_data` gives exclusive access to a valid `DescriptorResult<Vec<Descriptor>>`.
210*d289c2baSAndroid Build Coastguard Worker let result = unsafe { (user_data as *mut DescriptorResult<Vec<Descriptor>>).as_mut() };
211*d289c2baSAndroid Build Coastguard Worker // We can always unwrap here because we never pass a NULL pointer as `user_data`.
212*d289c2baSAndroid Build Coastguard Worker let result = result.unwrap();
213*d289c2baSAndroid Build Coastguard Worker
214*d289c2baSAndroid Build Coastguard Worker // SAFETY: caller ensures that `descriptor` points to a valid `AvbDescriptor` with header and
215*d289c2baSAndroid Build Coastguard Worker // body contents, which remains unmodified at least as long as the new `Descriptor`.
216*d289c2baSAndroid Build Coastguard Worker match unsafe { Descriptor::new(descriptor) } {
217*d289c2baSAndroid Build Coastguard Worker Ok(d) => {
218*d289c2baSAndroid Build Coastguard Worker // We can always unwrap here because this function will never be called with an error
219*d289c2baSAndroid Build Coastguard Worker // in `result`, since we stop iteration as soon as we encounter an error.
220*d289c2baSAndroid Build Coastguard Worker result.as_mut().unwrap().push(d);
221*d289c2baSAndroid Build Coastguard Worker true
222*d289c2baSAndroid Build Coastguard Worker }
223*d289c2baSAndroid Build Coastguard Worker Err(e) => {
224*d289c2baSAndroid Build Coastguard Worker // Set the error and stop iteration early.
225*d289c2baSAndroid Build Coastguard Worker *result = Err(e);
226*d289c2baSAndroid Build Coastguard Worker false
227*d289c2baSAndroid Build Coastguard Worker }
228*d289c2baSAndroid Build Coastguard Worker }
229*d289c2baSAndroid Build Coastguard Worker }
230*d289c2baSAndroid Build Coastguard Worker
231*d289c2baSAndroid Build Coastguard Worker #[cfg(test)]
232*d289c2baSAndroid Build Coastguard Worker mod tests {
233*d289c2baSAndroid Build Coastguard Worker use super::*;
234*d289c2baSAndroid Build Coastguard Worker
235*d289c2baSAndroid Build Coastguard Worker #[test]
new_unknown_descriptor()236*d289c2baSAndroid Build Coastguard Worker fn new_unknown_descriptor() {
237*d289c2baSAndroid Build Coastguard Worker // A fake descriptor which is valid but with an unknown tag.
238*d289c2baSAndroid Build Coastguard Worker let data: &[u8] = &[
239*d289c2baSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, // tag = 0x42u64 (BE)
240*d289c2baSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // num_bytes_following = 8u64 (BE)
241*d289c2baSAndroid Build Coastguard Worker 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // fake contents
242*d289c2baSAndroid Build Coastguard Worker ];
243*d289c2baSAndroid Build Coastguard Worker
244*d289c2baSAndroid Build Coastguard Worker // SAFETY: we've crafted a valid descriptor in `data`.
245*d289c2baSAndroid Build Coastguard Worker let descriptor = unsafe { Descriptor::new(data.as_ptr() as *const _) }.unwrap();
246*d289c2baSAndroid Build Coastguard Worker
247*d289c2baSAndroid Build Coastguard Worker let contents = match descriptor {
248*d289c2baSAndroid Build Coastguard Worker Descriptor::Unknown(c) => c,
249*d289c2baSAndroid Build Coastguard Worker d => panic!("Expected Unknown descriptor, got {d:?}"),
250*d289c2baSAndroid Build Coastguard Worker };
251*d289c2baSAndroid Build Coastguard Worker assert_eq!(data, contents);
252*d289c2baSAndroid Build Coastguard Worker }
253*d289c2baSAndroid Build Coastguard Worker
254*d289c2baSAndroid Build Coastguard Worker #[test]
new_invalid_descriptor_length_fails()255*d289c2baSAndroid Build Coastguard Worker fn new_invalid_descriptor_length_fails() {
256*d289c2baSAndroid Build Coastguard Worker // `avb_descriptor_validate_and_byteswap()` should detect and reject descriptors whose
257*d289c2baSAndroid Build Coastguard Worker // `num_bytes_following` is not 8-byte aligned.
258*d289c2baSAndroid Build Coastguard Worker let data: &[u8] = &[
259*d289c2baSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, // tag = 0x42u64 (BE)
260*d289c2baSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, // num_bytes_following = 7u64 (BE)
261*d289c2baSAndroid Build Coastguard Worker 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // fake contents
262*d289c2baSAndroid Build Coastguard Worker ];
263*d289c2baSAndroid Build Coastguard Worker
264*d289c2baSAndroid Build Coastguard Worker assert_eq!(
265*d289c2baSAndroid Build Coastguard Worker // SAFETY: we've created an invalid descriptor in a way that should be detected and
266*d289c2baSAndroid Build Coastguard Worker // fail safely without triggering any undefined behavior.
267*d289c2baSAndroid Build Coastguard Worker unsafe { Descriptor::new(data.as_ptr() as *const _) }.unwrap_err(),
268*d289c2baSAndroid Build Coastguard Worker DescriptorError::InvalidHeader
269*d289c2baSAndroid Build Coastguard Worker );
270*d289c2baSAndroid Build Coastguard Worker }
271*d289c2baSAndroid Build Coastguard Worker }
272