Skip to content

Commit e1ca2c8

Browse files
committed
make_boxed: add tests for different alignments
1 parent 50f487c commit e1ca2c8

File tree

1 file changed

+55
-14
lines changed

1 file changed

+55
-14
lines changed

uefi/src/mem.rs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ mod tests {
7575
use crate::ResultExt;
7676
use core::mem::{align_of, size_of};
7777

78+
/// Some simple dummy type to test [`make_boxed`].
7879
#[derive(Debug)]
7980
#[repr(C)]
8081
struct SomeData([u8; 4]);
@@ -85,53 +86,93 @@ mod tests {
8586
}
8687
}
8788

89+
/// Type wrapper that ensures an alignment of 16 for the underlying data.
90+
#[derive(Debug)]
91+
#[repr(C, align(16))]
92+
struct Align16<T>(T);
93+
94+
/// Version of [`SomeData`] that has an alignment of 16.
95+
type SomeDataAlign16 = Align16<SomeData>;
96+
97+
impl Align for SomeDataAlign16 {
98+
fn alignment() -> usize {
99+
align_of::<Self>()
100+
}
101+
}
102+
88103
/// Function that behaves like the other UEFI functions. It takes a
89104
/// mutable reference to a buffer memory that represents a [`SomeData`]
90105
/// instance.
91-
fn uefi_function_stub_read(buf: &mut [u8]) -> Result<&mut SomeData, Option<usize>> {
92-
if buf.len() < 4 {
93-
return Status::BUFFER_TOO_SMALL.into_with(|| panic!(), |_| Some(4));
106+
fn uefi_function_stub_read<Data: Align>(buf: &mut [u8]) -> Result<&mut Data, Option<usize>> {
107+
let required_size = size_of::<Data>();
108+
109+
if buf.len() < required_size {
110+
// We can use an zero-length buffer to find the required size.
111+
return Status::BUFFER_TOO_SMALL.into_with(|| panic!(), |_| Some(required_size));
94112
};
95113

114+
// assert alignment
115+
assert_eq!(
116+
buf.as_ptr() as usize % Data::alignment(),
117+
0,
118+
"The buffer must be correctly aligned!"
119+
);
120+
96121
buf[0] = 1;
97122
buf[1] = 2;
98123
buf[2] = 3;
99124
buf[3] = 4;
100125

101-
let data = unsafe { &mut *buf.as_mut_ptr().cast::<SomeData>() };
126+
let data = unsafe { &mut *buf.as_mut_ptr().cast::<Data>() };
102127

103128
Ok(data)
104129
}
105130

106-
// Some basic checks so that miri reports everything is fine.
131+
// Some basic sanity checks so that we can catch problems that miri would detect early.
107132
#[test]
108-
fn some_data_type_size_constraints() {
133+
fn test_some_data_type_size_constraints() {
109134
assert_eq!(size_of::<SomeData>(), 4);
110-
assert_eq!(align_of::<SomeData>(), 1);
135+
assert_eq!(SomeData::alignment(), 1);
136+
assert_eq!(
137+
size_of::<SomeDataAlign16>(),
138+
16,
139+
"The size must be 16 instead of 4, as in Rust the runtime size is a multiple of the alignment."
140+
);
141+
assert_eq!(SomeDataAlign16::alignment(), 16);
111142
}
112143

144+
// Tests `uefi_function_stub_read` which is the foundation for the `test_make_boxed_utility`
145+
// test.
113146
#[test]
114-
fn basic_stub_read() {
147+
fn test_basic_stub_read() {
115148
assert_eq!(
116-
uefi_function_stub_read(&mut []).status(),
149+
uefi_function_stub_read::<SomeData>(&mut []).status(),
117150
Status::BUFFER_TOO_SMALL
118151
);
119152
assert_eq!(
120-
*uefi_function_stub_read(&mut []).unwrap_err().data(),
153+
*uefi_function_stub_read::<SomeData>(&mut [])
154+
.unwrap_err()
155+
.data(),
121156
Some(4)
122157
);
123158

124159
let mut buf: [u8; 4] = [0; 4];
125-
let data = uefi_function_stub_read(&mut buf).unwrap();
160+
let data: &mut SomeData = uefi_function_stub_read(&mut buf).unwrap();
161+
assert_eq!(&data.0, &[1, 2, 3, 4]);
126162

127-
assert_eq!(&data.0, &[1, 2, 3, 4])
163+
let mut buf: Align16<[u8; 16]> = Align16([0; 16]);
164+
let data: &mut SomeDataAlign16 = uefi_function_stub_read(&mut buf.0).unwrap();
165+
assert_eq!(&data.0 .0, &[1, 2, 3, 4]);
128166
}
129167

130168
#[test]
131-
fn make_boxed_utility() {
169+
fn test_make_boxed_utility() {
132170
let fetch_data_fn = |buf| uefi_function_stub_read(buf);
133171
let data: Box<SomeData> = make_boxed(fetch_data_fn).unwrap();
172+
assert_eq!(&data.0, &[1, 2, 3, 4]);
134173

135-
assert_eq!(&data.0, &[1, 2, 3, 4])
174+
let fetch_data_fn = |buf| uefi_function_stub_read(buf);
175+
let data: Box<SomeDataAlign16> = make_boxed(fetch_data_fn).unwrap();
176+
assert_eq!(&data.0 .0, &[1, 2, 3, 4]);
136177
}
137178
}

0 commit comments

Comments
 (0)