Skip to content

Commit e1b7ffb

Browse files
committed
multiboot2-header: Make from_addr return a Result
1 parent a190e48 commit e1b7ffb

File tree

1 file changed

+28
-33
lines changed

1 file changed

+28
-33
lines changed

multiboot2-header/src/header.rs

+28-33
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@ pub struct Multiboot2Header<'a> {
2323
}
2424

2525
impl<'a> Multiboot2Header<'a> {
26-
/// Public constructor for this type with various validations. It panics if the address is invalid.
27-
/// It panics rather than returning a result, because if this fails, it is
28-
/// a fatal, unrecoverable error anyways and a bug in your code.
26+
/// Public constructor for this type with various validations.
2927
///
30-
/// # Panics
31-
/// Panics if one of the following conditions is true:
28+
/// If the header is invalid, it returns a [`LoadError`].
29+
/// This may be because:
3230
/// - `addr` is a null-pointer
3331
/// - `addr` isn't 8-byte aligned
3432
/// - the magic value of the header is not present
@@ -37,38 +35,31 @@ impl<'a> Multiboot2Header<'a> {
3735
/// # Safety
3836
/// This function may produce undefined behaviour, if the provided `addr` is not a valid
3937
/// Multiboot2 header pointer.
40-
pub unsafe fn from_addr(addr: usize) -> Self {
41-
assert_ne!(0, addr, "`addr` is null pointer");
42-
assert_eq!(
43-
addr % 8,
44-
0,
45-
"`addr` must be 8-byte aligned, see Multiboot2 spec"
46-
);
38+
// This function can be `const` on newer Rust versions.
39+
#[allow(clippy::missing_const_for_fn)]
40+
pub unsafe fn from_addr(addr: usize) -> Result<Self, LoadError> {
41+
if addr == 0 || addr % 8 != 0 {
42+
return Err(LoadError::InvalidAddress);
43+
}
4744
let ptr = addr as *const Multiboot2BasicHeader;
4845
let reference = &*ptr;
49-
assert_eq!(
50-
reference.header_magic(),
51-
MULTIBOOT2_HEADER_MAGIC,
52-
"The Multiboot2 header must contain the MULTIBOOT2_HEADER_MAGIC={:x}",
53-
MULTIBOOT2_HEADER_MAGIC
54-
);
55-
assert!(
56-
reference.verify_checksum(),
57-
"checksum invalid! Is {:x}, expected {:x}",
58-
reference.checksum(),
59-
Self::calc_checksum(reference.header_magic, reference.arch, reference.length)
60-
);
61-
Self { inner: reference }
46+
if reference.header_magic() != MULTIBOOT2_HEADER_MAGIC {
47+
return Err(LoadError::MagicNotFound);
48+
}
49+
if !reference.verify_checksum() {
50+
return Err(LoadError::ChecksumMismatch);
51+
}
52+
Ok(Self { inner: reference })
6253
}
6354

6455
/// Find the header in a given slice.
6556
///
6657
/// If it succeeds, it returns a tuple consisting of the subslice containing
6758
/// just the header and the index of the header in the given slice.
6859
/// If it fails (either because the header is not properply 64-bit aligned
69-
/// or because it is truncated), it returns a [`BufError`].
60+
/// or because it is truncated), it returns a [`LoadError`].
7061
/// If there is no header, it returns `None`.
71-
pub fn find_header(buffer: &[u8]) -> Result<Option<(&[u8], u32)>, BufError> {
62+
pub fn find_header(buffer: &[u8]) -> Result<Option<(&[u8], u32)>, LoadError> {
7263
// the magic is 32 bit aligned and inside the first 8192 bytes
7364
assert!(buffer.len() >= 8192);
7465
let mut windows = buffer[0..8192].windows(4);
@@ -80,7 +71,7 @@ impl<'a> Multiboot2Header<'a> {
8071
if idx % 8 == 0 {
8172
idx
8273
} else {
83-
return Err(BufError::Unaligned);
74+
return Err(LoadError::InvalidAddress);
8475
}
8576
}
8677
None => return Ok(None),
@@ -97,7 +88,7 @@ impl<'a> Multiboot2Header<'a> {
9788
let header_length: usize = u32::from_le_bytes(
9889
windows
9990
.next()
100-
.ok_or(BufError::TooSmall)?
91+
.ok_or(LoadError::TooSmall)?
10192
.try_into()
10293
.unwrap(), // 4 bytes are a u32
10394
)
@@ -210,11 +201,15 @@ impl<'a> Debug for Multiboot2Header<'a> {
210201
/// Errors that can occur when parsing a header from a slice.
211202
/// See [`Multiboot2Header::find_header`].
212203
#[derive(Debug, Clone, PartialEq, Eq)]
213-
pub enum BufError {
214-
/// The header in the given slice is truncated.
204+
pub enum LoadError {
205+
/// The checksum does not match the data.
206+
ChecksumMismatch,
207+
/// The header is not properly 64-bit aligned (or a null pointer).
208+
InvalidAddress,
209+
/// The header does not contain the correct magic number.
210+
MagicNotFound,
211+
/// The header is truncated.
215212
TooSmall,
216-
/// The header in the given slice is not properly 64-bit aligned.
217-
Unaligned,
218213
}
219214

220215
/// **Use this only if you know what you do. You probably want to use

0 commit comments

Comments
 (0)