Merge "pvmfw: Unify Config::new() calls into a single one" into main
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index 253604b..72212c3 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -403,12 +403,6 @@
     unsafe { slice::from_raw_parts_mut(range.start.0 as *mut u8, range.end - range.start) }
 }
 
-enum AppendedConfigType {
-    Valid,
-    Invalid,
-    NotFound,
-}
-
 enum AppendedPayload<'a> {
     /// Configuration data.
     Config(config::Config<'a>),
@@ -418,35 +412,29 @@
 
 impl<'a> AppendedPayload<'a> {
     fn new(data: &'a mut [u8]) -> Option<Self> {
-        match Self::guess_config_type(data) {
-            AppendedConfigType::Valid => {
-                let config = config::Config::new(data);
-                Some(Self::Config(config.unwrap()))
-            }
-            AppendedConfigType::NotFound if cfg!(feature = "legacy") => {
+        // The borrow checker gets confused about the ownership of data (see inline comments) so we
+        // intentionally obfuscate it using a raw pointer; see a similar issue (still not addressed
+        // in v1.77) in https://users.rust-lang.org/t/78467.
+        let data_ptr = data as *mut [u8];
+
+        // Config::new() borrows data as mutable ...
+        match config::Config::new(data) {
+            // ... so this branch has a mutable reference to data, from the Ok(Config<'a>). But ...
+            Ok(valid) => Some(Self::Config(valid)),
+            // ... if Config::new(data).is_err(), the Err holds no ref to data. However ...
+            Err(config::Error::InvalidMagic) if cfg!(feature = "legacy") => {
+                // ... the borrow checker still complains about a second mutable ref without this.
+                // SAFETY: Pointer to a valid mut (not accessed elsewhere), 'a lifetime re-used.
+                let data: &'a mut _ = unsafe { &mut *data_ptr };
+
                 const BCC_SIZE: usize = SIZE_4KB;
                 warn!("Assuming the appended data at {:?} to be a raw BCC", data.as_ptr());
                 Some(Self::LegacyBcc(&mut data[..BCC_SIZE]))
             }
-            _ => None,
-        }
-    }
-
-    fn guess_config_type(data: &mut [u8]) -> AppendedConfigType {
-        // This function is necessary to prevent the borrow checker from getting confused
-        // about the ownership of data in new(); see https://users.rust-lang.org/t/78467.
-        let addr = data.as_ptr();
-
-        match config::Config::new(data) {
-            Err(config::Error::InvalidMagic) => {
-                warn!("No configuration data found at {addr:?}");
-                AppendedConfigType::NotFound
-            }
             Err(e) => {
-                error!("Invalid configuration data at {addr:?}: {e}");
-                AppendedConfigType::Invalid
+                error!("Invalid configuration data at {data_ptr:?}: {e}");
+                None
             }
-            Ok(_) => AppendedConfigType::Valid,
         }
     }