Skip to content

Commit 999e48d

Browse files
committed
uefi: Fix unaligned memcpy in ConfigurationString parser
1 parent e4dddc6 commit 999e48d

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

uefi/src/mem/aligned_buffer.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
use alloc::alloc::{Layout, LayoutError, alloc, dealloc};
44
use core::error::Error;
5-
use core::fmt;
65
use core::ptr::NonNull;
6+
use core::{fmt, slice};
77

88
/// Helper class to maintain the lifetime of a memory region allocated with a non-standard alignment.
99
/// Facilitates RAII to properly deallocate when lifetime of the object ends.
@@ -51,6 +51,18 @@ impl AlignedBuffer {
5151
self.ptr.as_ptr()
5252
}
5353

54+
/// Get the underlying memory region as immutable slice.
55+
#[must_use]
56+
pub const fn as_slice(&mut self) -> &[u8] {
57+
unsafe { slice::from_raw_parts(self.ptr(), self.size()) }
58+
}
59+
60+
/// Get the underlying memory region as mutable slice.
61+
#[must_use]
62+
pub const fn as_slice_mut(&mut self) -> &mut [u8] {
63+
unsafe { slice::from_raw_parts_mut(self.ptr_mut(), self.size()) }
64+
}
65+
5466
/// Get the size of the aligned memory region managed by this instance.
5567
#[must_use]
5668
pub const fn size(&self) -> usize {
@@ -67,6 +79,14 @@ impl AlignedBuffer {
6779
}
6880
}
6981

82+
/// Fill the aligned memory region with data from the given iterator.
83+
/// If the given iterator is shorter than the buffer, the remaining area will be left untouched.
84+
pub fn copy_from_iter(&mut self, src: impl Iterator<Item = u8>) {
85+
src.take(self.size())
86+
.zip(self.as_slice_mut().iter_mut())
87+
.for_each(|(src, dst)| *dst = src);
88+
}
89+
7090
/// Check the buffer's alignment against the `required_alignment`.
7191
pub fn check_alignment(&self, required_alignment: usize) -> Result<(), AlignmentError> {
7292
//TODO: use bfr.addr() when it's available

uefi/src/proto/hii/config_str.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use core::slice;
99
use core::str::{self, FromStr};
1010
use uguid::Guid;
1111

12+
use crate::mem::AlignedBuffer;
1213
use crate::proto::device_path::DevicePath;
1314
use crate::{CStr16, Char16};
1415

@@ -169,11 +170,15 @@ impl ConfigurationString {
169170
if data.len() % 2 != 0 {
170171
return None;
171172
}
172-
let mut data: Vec<_> = Self::parse_bytes_from_hex(data).collect();
173-
data.chunks_exact_mut(2).for_each(|c| c.swap(0, 1));
174-
data.extend_from_slice(&[0, 0]);
173+
let size_bytes = data.len() / 2 + 2; // includes \0 terminator
174+
let size_chars = size_bytes / 2;
175+
let mut bfr = AlignedBuffer::from_size_align(size_bytes, 2).ok()?;
176+
bfr.copy_from_iter(Self::parse_bytes_from_hex(data).chain([0, 0]));
177+
bfr.as_slice_mut()
178+
.chunks_exact_mut(2)
179+
.for_each(|c| c.swap(0, 1));
175180
let data: &[Char16] =
176-
unsafe { slice::from_raw_parts(data.as_slice().as_ptr().cast(), data.len() / 2) };
181+
unsafe { slice::from_raw_parts(bfr.as_slice().as_ptr().cast(), size_chars) };
177182
Some(CStr16::from_char16_with_nul(data).ok()?.to_string())
178183
}
179184

0 commit comments

Comments
 (0)