mirror of
https://github.com/edera-dev/sprout.git
synced 2026-11-04 18:42:21 +00:00
fix(variables): accept UTF-16 values without a NUL terminator
EFI string variables written without a trailing NUL, or with extra NUL padding, failed to decode and were silently treated as unset. Decode up to the first NUL and terminate the string ourselves, as systemd-boot does. Because empty values now decode to an empty string rather than failing, treat empty LoaderEntryDefault and LoaderEntryOneShot values as unset so an empty one-shot entry doesn't fail to match any entry.
This commit is contained in:
1 parent
df5d8f5c39
commit
ad37a2bcf3
2 files changed
+13
-4
No files matched your search
@@ -295,9 +295,11 @@ impl BootloaderInterface {
|
|||||||
|
|
||||||
/// Get the default entry set by the bootloader interface.
|
/// Get the default entry set by the bootloader interface.
|
||||||
pub fn get_default_entry() -> Result<Option<String>> {
|
pub fn get_default_entry() -> Result<Option<String>> {
|
||||||
Self::VENDOR
|
// An empty value is treated as if the default entry was not set.
|
||||||
|
Ok(Self::VENDOR
|
||||||
.get_cstr16("LoaderEntryDefault")
|
.get_cstr16("LoaderEntryDefault")
|
||||||
.context("unable to get default entry from bootloader interface")
|
.context("unable to get default entry from bootloader interface")?
|
||||||
|
.filter(|value| !value.is_empty()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the oneshot entry set by the bootloader interface.
|
/// Get the oneshot entry set by the bootloader interface.
|
||||||
@@ -318,6 +320,7 @@ impl BootloaderInterface {
|
|||||||
.context("unable to remove oneshot entry")?;
|
.context("unable to remove oneshot entry")?;
|
||||||
|
|
||||||
// Return the oneshot value.
|
// Return the oneshot value.
|
||||||
Ok(Some(value))
|
// An empty value is treated as if the oneshot entry was not set.
|
||||||
|
Ok(Some(value).filter(|value| !value.is_empty()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,15 +10,21 @@ pub fn utf16_bytes_to_cstring16(bytes: &[u8]) -> Result<CString16> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the bytes to UTF-16 data.
|
// Convert the bytes to UTF-16 data.
|
||||||
let data = bytes
|
let mut data = bytes
|
||||||
// Chunk everything into two bytes.
|
// Chunk everything into two bytes.
|
||||||
.as_chunks::<2>()
|
.as_chunks::<2>()
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
// Reinterpret the bytes as u16 little-endian.
|
// Reinterpret the bytes as u16 little-endian.
|
||||||
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
|
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
|
||||||
|
// Stop at the first null terminator, if any.
|
||||||
|
// This ignores any trailing data, such as extra null padding.
|
||||||
|
.take_while(|c| *c != 0)
|
||||||
// Collect the result into a vector.
|
// Collect the result into a vector.
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Add the null terminator, as the input is not guaranteed to be null-terminated.
|
||||||
|
data.push(0);
|
||||||
|
|
||||||
CString16::try_from(data).context("unable to convert utf16 bytes to CString16")
|
CString16::try_from(data).context("unable to convert utf16 bytes to CString16")
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user