Переглянути джерело

multiboot2-header: Make from_addr return a Result

Niklas Sombert 1 рік тому
батько
коміт
e1b7ffb3f2
1 змінених файлів з 28 додано та 33 видалено
  1. 28 33
      multiboot2-header/src/header.rs

+ 28 - 33
multiboot2-header/src/header.rs

@@ -23,12 +23,10 @@ pub struct Multiboot2Header<'a> {
 }
 
 impl<'a> Multiboot2Header<'a> {
-    /// Public constructor for this type with various validations. It panics if the address is invalid.
-    /// It panics rather than returning a result, because if this fails, it is
-    /// a fatal, unrecoverable error anyways and a bug in your code.
+    /// Public constructor for this type with various validations.
     ///
-    /// # Panics
-    /// Panics if one of the following conditions is true:
+    /// If the header is invalid, it returns a [`LoadError`].
+    /// This may be because:
     /// - `addr` is a null-pointer
     /// - `addr` isn't 8-byte aligned
     /// - the magic value of the header is not present
@@ -37,28 +35,21 @@ impl<'a> Multiboot2Header<'a> {
     /// # Safety
     /// This function may produce undefined behaviour, if the provided `addr` is not a valid
     /// Multiboot2 header pointer.
-    pub unsafe fn from_addr(addr: usize) -> Self {
-        assert_ne!(0, addr, "`addr` is null pointer");
-        assert_eq!(
-            addr % 8,
-            0,
-            "`addr` must be 8-byte aligned, see Multiboot2 spec"
-        );
+    // This function can be `const` on newer Rust versions.
+    #[allow(clippy::missing_const_for_fn)]
+    pub unsafe fn from_addr(addr: usize) -> Result<Self, LoadError> {
+        if addr == 0 || addr % 8 != 0 {
+            return Err(LoadError::InvalidAddress);
+        }
         let ptr = addr as *const Multiboot2BasicHeader;
         let reference = &*ptr;
-        assert_eq!(
-            reference.header_magic(),
-            MULTIBOOT2_HEADER_MAGIC,
-            "The Multiboot2 header must contain the MULTIBOOT2_HEADER_MAGIC={:x}",
-            MULTIBOOT2_HEADER_MAGIC
-        );
-        assert!(
-            reference.verify_checksum(),
-            "checksum invalid! Is {:x}, expected {:x}",
-            reference.checksum(),
-            Self::calc_checksum(reference.header_magic, reference.arch, reference.length)
-        );
-        Self { inner: reference }
+        if reference.header_magic() != MULTIBOOT2_HEADER_MAGIC {
+            return Err(LoadError::MagicNotFound);
+        }
+        if !reference.verify_checksum() {
+            return Err(LoadError::ChecksumMismatch);
+        }
+        Ok(Self { inner: reference })
     }
 
     /// Find the header in a given slice.
@@ -66,9 +57,9 @@ impl<'a> Multiboot2Header<'a> {
     /// If it succeeds, it returns a tuple consisting of the subslice containing
     /// just the header and the index of the header in the given slice.
     /// If it fails (either because the header is not properply 64-bit aligned
-    /// or because it is truncated), it returns a [`BufError`].
+    /// or because it is truncated), it returns a [`LoadError`].
     /// If there is no header, it returns `None`.
-    pub fn find_header(buffer: &[u8]) -> Result<Option<(&[u8], u32)>, BufError> {
+    pub fn find_header(buffer: &[u8]) -> Result<Option<(&[u8], u32)>, LoadError> {
         // the magic is 32 bit aligned and inside the first 8192 bytes
         assert!(buffer.len() >= 8192);
         let mut windows = buffer[0..8192].windows(4);
@@ -80,7 +71,7 @@ impl<'a> Multiboot2Header<'a> {
                 if idx % 8 == 0 {
                     idx
                 } else {
-                    return Err(BufError::Unaligned);
+                    return Err(LoadError::InvalidAddress);
                 }
             }
             None => return Ok(None),
@@ -97,7 +88,7 @@ impl<'a> Multiboot2Header<'a> {
         let header_length: usize = u32::from_le_bytes(
             windows
                 .next()
-                .ok_or(BufError::TooSmall)?
+                .ok_or(LoadError::TooSmall)?
                 .try_into()
                 .unwrap(), // 4 bytes are a u32
         )
@@ -210,11 +201,15 @@ impl<'a> Debug for Multiboot2Header<'a> {
 /// Errors that can occur when parsing a header from a slice.
 /// See [`Multiboot2Header::find_header`].
 #[derive(Debug, Clone, PartialEq, Eq)]
-pub enum BufError {
-    /// The header in the given slice is truncated.
+pub enum LoadError {
+    /// The checksum does not match the data.
+    ChecksumMismatch,
+    /// The header is not properly 64-bit aligned (or a null pointer).
+    InvalidAddress,
+    /// The header does not contain the correct magic number.
+    MagicNotFound,
+    /// The header is truncated.
     TooSmall,
-    /// The header in the given slice is not properly 64-bit aligned.
-    Unaligned,
 }
 
 /// **Use this only if you know what you do. You probably want to use