Skip to content

Commit 5fdccbd

Browse files
committed
make_boxed: add tests for different alignments
1 parent f612991 commit 5fdccbd

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

uefi/src/mem.rs

Lines changed: 56 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,94 @@ 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 early that miri would detect
132+
// otherwise.
107133
#[test]
108-
fn some_data_type_size_constraints() {
134+
fn test_some_data_type_size_constraints() {
109135
assert_eq!(size_of::<SomeData>(), 4);
110-
assert_eq!(align_of::<SomeData>(), 1);
136+
assert_eq!(SomeData::alignment(), 1);
137+
assert_eq!(
138+
size_of::<SomeDataAlign16>(),
139+
16,
140+
"The size must be 16 instead of 4, as in Rust the runtime size is a multiple of the alignment."
141+
);
142+
assert_eq!(SomeDataAlign16::alignment(), 16);
111143
}
112144

145+
// Tests `uefi_function_stub_read` which is the foundation for the `test_make_boxed_utility`
146+
// test.
113147
#[test]
114-
fn basic_stub_read() {
148+
fn test_basic_stub_read() {
115149
assert_eq!(
116-
uefi_function_stub_read(&mut []).status(),
150+
uefi_function_stub_read::<SomeData>(&mut []).status(),
117151
Status::BUFFER_TOO_SMALL
118152
);
119153
assert_eq!(
120-
*uefi_function_stub_read(&mut []).unwrap_err().data(),
154+
*uefi_function_stub_read::<SomeData>(&mut [])
155+
.unwrap_err()
156+
.data(),
121157
Some(4)
122158
);
123159

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

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

130169
#[test]
131-
fn make_boxed_utility() {
170+
fn test_make_boxed_utility() {
132171
let fetch_data_fn = |buf| uefi_function_stub_read(buf);
133172
let data: Box<SomeData> = make_boxed(fetch_data_fn).unwrap();
173+
assert_eq!(&data.0, &[1, 2, 3, 4]);
134174

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

0 commit comments

Comments
 (0)