Skip to content

Commit a10e2f8

Browse files
committed
workspace: streamline error types for load() functions
1 parent 16915e1 commit a10e2f8

File tree

7 files changed

+52
-30
lines changed

7 files changed

+52
-30
lines changed

multiboot2-common/src/bytes_ref.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl<'a, H: Header> TryFrom<&'a [u8]> for BytesRef<'a, H> {
2222

2323
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
2424
if bytes.len() < mem::size_of::<H>() {
25-
return Err(MemoryError::MinLengthNotSatisfied);
25+
return Err(MemoryError::ShorterThanHeader);
2626
}
2727
// Doesn't work as expected: if align_of_val(&value[0]) < ALIGNMENT {
2828
if bytes.as_ptr().align_offset(ALIGNMENT) != 0 {
@@ -57,13 +57,13 @@ mod tests {
5757
let empty: &[u8] = &[];
5858
assert_eq!(
5959
BytesRef::<'_, DummyTestHeader>::try_from(empty),
60-
Err(MemoryError::MinLengthNotSatisfied)
60+
Err(MemoryError::ShorterThanHeader)
6161
);
6262

6363
let slice = &[0_u8, 1, 2, 3, 4, 5, 6];
6464
assert_eq!(
6565
BytesRef::<'_, DummyTestHeader>::try_from(&slice[..]),
66-
Err(MemoryError::MinLengthNotSatisfied)
66+
Err(MemoryError::ShorterThanHeader)
6767
);
6868

6969
let slice = AlignedBytes([0_u8, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0]);

multiboot2-common/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ impl<H: Header> DynSizedStructure<H> {
225225
let hdr = unsafe { &*ptr };
226226

227227
if hdr.payload_len() > bytes.len() {
228-
return Err(MemoryError::InvalidHeaderSize);
228+
return Err(MemoryError::InvalidReportedTotalSize);
229229
}
230230

231231
// At this point we know that the memory slice fulfills the base
@@ -308,14 +308,14 @@ pub enum MemoryError {
308308
WrongAlignment,
309309
/// The memory must cover at least the length of the sized structure header
310310
/// type.
311-
MinLengthNotSatisfied,
311+
ShorterThanHeader,
312312
/// The buffer misses the terminating padding to the next alignment
313313
/// boundary. The padding is relevant to satisfy Rustc/Miri, but also the
314314
/// spec mandates that the padding is added.
315315
MissingPadding,
316316
/// The size-property has an illegal value that can't be fulfilled with the
317317
/// given bytes.
318-
InvalidHeaderSize,
318+
InvalidReportedTotalSize,
319319
}
320320

321321
#[cfg(feature = "unstable")]

multiboot2-header/Changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ place, please head to the documentation of `multiboot2-common`.
1313
- **Breaking** All functions that returns something useful are now `#[must_use]`
1414
- **Breaking** The builder type is now just called `Builder`. This needs the
1515
`builder` feature.
16+
- **Breaking:** The error type returned by `Multiboot2Header::load` has been
17+
changed.
1618
- Updated to latest `multiboot2` dependency
1719

1820
## 0.4.0 (2024-05-01)

multiboot2-header/src/header.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ use crate::{
44
HeaderTagType, InformationRequestHeaderTag, ModuleAlignHeaderTag, RelocatableHeaderTag,
55
TagIter,
66
};
7+
#[cfg(feature = "unstable")]
8+
use core::error::Error;
79
use core::fmt::{Debug, Formatter};
810
use core::mem::size_of;
911
use core::ptr::NonNull;
10-
use multiboot2_common::{DynSizedStructure, Header, Tag, ALIGNMENT};
12+
use multiboot2_common::{DynSizedStructure, Header, MemoryError, Tag, ALIGNMENT};
1113

1214
/// Magic value for a [`Multiboot2Header`], as defined by the spec.
1315
pub const MAGIC: u32 = 0xe85250d6;
@@ -35,8 +37,8 @@ impl<'a> Multiboot2Header<'a> {
3537
/// This function may produce undefined behaviour, if the provided `addr` is not a valid
3638
/// Multiboot2 header pointer.
3739
pub unsafe fn load(ptr: *const Multiboot2BasicHeader) -> Result<Self, LoadError> {
38-
let ptr = NonNull::new(ptr.cast_mut()).ok_or(LoadError::InvalidAddress)?;
39-
let inner = DynSizedStructure::ref_from_ptr(ptr).map_err(|_e| LoadError::TooSmall)?;
40+
let ptr = NonNull::new(ptr.cast_mut()).ok_or(LoadError::Memory(MemoryError::Null))?;
41+
let inner = DynSizedStructure::ref_from_ptr(ptr).map_err(LoadError::Memory)?;
4042
let this = Self(inner);
4143

4244
let header = this.0.header();
@@ -58,7 +60,7 @@ impl<'a> Multiboot2Header<'a> {
5860
/// If there is no header, it returns `None`.
5961
pub fn find_header(buffer: &[u8]) -> Result<Option<(&[u8], u32)>, LoadError> {
6062
if buffer.as_ptr().align_offset(ALIGNMENT) != 0 {
61-
return Err(LoadError::InvalidAddress);
63+
return Err(LoadError::Memory(MemoryError::WrongAlignment));
6264
}
6365

6466
let mut windows = buffer[0..8192].windows(4);
@@ -70,7 +72,7 @@ impl<'a> Multiboot2Header<'a> {
7072
if idx % 8 == 0 {
7173
idx
7274
} else {
73-
return Err(LoadError::InvalidAddress);
75+
return Err(LoadError::Memory(MemoryError::WrongAlignment));
7476
}
7577
}
7678
None => return Ok(None),
@@ -87,7 +89,7 @@ impl<'a> Multiboot2Header<'a> {
8789
let header_length: usize = u32::from_le_bytes(
8890
windows
8991
.next()
90-
.ok_or(LoadError::TooSmall)?
92+
.ok_or(LoadError::Memory(MemoryError::MissingPadding))?
9193
.try_into()
9294
.unwrap(), // 4 bytes are a u32
9395
)
@@ -221,22 +223,28 @@ impl Debug for Multiboot2Header<'_> {
221223
}
222224
}
223225

224-
/// Errors that can occur when parsing a header from a slice.
225-
/// See [`Multiboot2Header::find_header`].
226+
/// Errors that occur when a chunk of memory can't be parsed as
227+
/// [`Multiboot2Header`].
226228
#[derive(Copy, Clone, Debug, derive_more::Display, PartialEq, Eq, PartialOrd, Ord, Hash)]
227229
pub enum LoadError {
228-
/// The checksum does not match the data.
230+
/// The provided checksum does not match the expected value.
229231
ChecksumMismatch,
230-
/// The header is not properly 64-bit aligned (or a null pointer).
231-
InvalidAddress,
232232
/// The header does not contain the correct magic number.
233233
MagicNotFound,
234-
/// The header is truncated.
235-
TooSmall,
234+
/// The provided memory can't be parsed as [`Multiboot2Header`].
235+
/// See [`MemoryError`].
236+
Memory(MemoryError),
236237
}
237238

238239
#[cfg(feature = "unstable")]
239-
impl core::error::Error for LoadError {}
240+
impl Error for LoadError {
241+
fn source(&self) -> Option<&(dyn Error + 'static)> {
242+
match self {
243+
Self::Memory(inner) => Some(inner),
244+
_ => None,
245+
}
246+
}
247+
}
240248

241249
/// The "basic" Multiboot2 header. This means only the properties, that are known during
242250
/// compile time. All other information are derived during runtime from the size property.

multiboot2/Changelog.md

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ place, please head to the documentation of `multiboot2-common`.
1818
- **Breaking:** The trait `TagTrait` was removed and was replaced by a new `Tag`
1919
trait coming from `multiboot2-common`. This only affects you if you provide
2020
custom tag types for the library.
21+
- **Breaking:** The error type returned by `BootInformation::load` has been
22+
changed.
2123

2224
**General Note on Safety and UB (TL;DR: Crate is Safe)**
2325

multiboot2/src/boot_information.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,34 @@ use crate::{
88
ElfSectionIter, ElfSectionsTag, EndTag, FramebufferTag, ImageLoadPhysAddrTag, MemoryMapTag,
99
ModuleIter, RsdpV1Tag, RsdpV2Tag, SmbiosTag, TagIter, TagType, VBEInfoTag,
1010
};
11+
#[cfg(feature = "unstable")]
12+
use core::error::Error;
1113
use core::fmt;
1214
use core::mem;
1315
use core::ptr::NonNull;
1416
use derive_more::Display;
1517
use multiboot2_common::{DynSizedStructure, Header, MaybeDynSized, MemoryError, Tag};
1618

17-
/// Error type that describes errors while loading/parsing a multiboot2 information structure
18-
/// from a given address.
19+
/// Errors that occur when a chunk of memory can't be parsed as
20+
/// [`BootInformation`].
1921
#[derive(Display, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
20-
pub enum MbiLoadError {
22+
pub enum LoadError {
23+
/// The provided memory can't be parsed as [`BootInformation`].
2124
/// See [`MemoryError`].
2225
Memory(MemoryError),
2326
/// Missing mandatory end tag.
2427
NoEndTag,
2528
}
2629

2730
#[cfg(feature = "unstable")]
28-
impl core::error::Error for MbiLoadError {}
31+
impl Error for LoadError {
32+
fn source(&self) -> Option<&(dyn Error + 'static)> {
33+
match self {
34+
Self::Memory(inner) => Some(inner),
35+
Self::NoEndTag => None,
36+
}
37+
}
38+
}
2939

3040
/// The basic header of a [`BootInformation`] as sized Rust type.
3141
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -91,13 +101,13 @@ impl<'a> BootInformation<'a> {
91101
/// boot environments, such as UEFI.
92102
/// * The memory at `ptr` must not be modified after calling `load` or the
93103
/// program may observe unsynchronized mutation.
94-
pub unsafe fn load(ptr: *const BootInformationHeader) -> Result<Self, MbiLoadError> {
95-
let ptr = NonNull::new(ptr.cast_mut()).ok_or(MbiLoadError::Memory(MemoryError::Null))?;
96-
let inner = DynSizedStructure::ref_from_ptr(ptr).map_err(MbiLoadError::Memory)?;
104+
pub unsafe fn load(ptr: *const BootInformationHeader) -> Result<Self, LoadError> {
105+
let ptr = NonNull::new(ptr.cast_mut()).ok_or(LoadError::Memory(MemoryError::Null))?;
106+
let inner = DynSizedStructure::ref_from_ptr(ptr).map_err(LoadError::Memory)?;
97107

98108
let this = Self(inner);
99109
if !this.has_valid_end_tag() {
100-
return Err(MbiLoadError::NoEndTag);
110+
return Err(LoadError::NoEndTag);
101111
}
102112
Ok(this)
103113
}

multiboot2/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ mod vbe_info;
8484

8585
pub use multiboot2_common::{DynSizedStructure, MaybeDynSized, Tag};
8686

87-
pub use boot_information::{BootInformation, BootInformationHeader, MbiLoadError};
87+
pub use boot_information::{BootInformation, BootInformationHeader, LoadError};
8888
pub use boot_loader_name::BootLoaderNameTag;
8989
#[cfg(feature = "builder")]
9090
pub use builder::Builder;
@@ -1098,7 +1098,7 @@ mod tests {
10981098
/// This test succeeds if it compiles.
10991099
fn mbi_load_error_implements_error() {
11001100
fn consumer<E: core::error::Error>(_e: E) {}
1101-
consumer(MbiLoadError::IllegalAddress)
1101+
consumer(LoadError::NoEndTag)
11021102
}
11031103

11041104
/// Example for a custom tag.

0 commit comments

Comments
 (0)