Skip to content

Commit 0d6ef41

Browse files
committed
chroe: properly perform checksums on partition table arrays
Some partitioning tools like ones based on libparted (parted and GParted) don't wipe the entire GPT partition name field before writing new partition names. Additionally, it is not guaranteed to be properly zeroed since the UEFI specification does not clearly state that. Use a dedicated raw buffer holding the entire partition name field without any conversion for performing checksums and serializations. Signed-off-by: Xinhui Yang <[email protected]>
1 parent 7bd1432 commit 0d6ef41

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

src/lib.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,9 @@ impl GPTHeader {
377377
}
378378

379379
/// A wrapper type for `String` that represents a partition's name.
380+
/// Also stores a copy of raw bytes in the partition name field.
380381
#[derive(Debug, Clone, PartialEq, Eq)]
381-
pub struct PartitionName(String);
382+
pub struct PartitionName(String, [u8; 72]);
382383

383384
impl PartitionName {
384385
/// Extracts a string slice containing the entire `PartitionName`.
@@ -395,7 +396,13 @@ impl std::fmt::Display for PartitionName {
395396

396397
impl From<&str> for PartitionName {
397398
fn from(value: &str) -> PartitionName {
398-
PartitionName(value.to_string())
399+
// Convert to UTF-16 LE and store in the raw buffer
400+
let utf16_converted = value.encode_utf16();
401+
let mut raw_buf = [0; 72];
402+
for (idx, chr) in utf16_converted.into_iter().take(36).enumerate() {
403+
raw_buf[idx * 2..=idx * 2 + 1].copy_from_slice(&chr.to_le_bytes());
404+
}
405+
PartitionName(value.to_string(), raw_buf)
399406
}
400407
}
401408

@@ -412,18 +419,25 @@ impl<'de> Visitor<'de> for UTF16LEVisitor {
412419
where
413420
A: SeqAccess<'de>,
414421
{
415-
let mut v = Vec::new();
422+
let mut v: Vec<u16> = Vec::new();
423+
let mut raw_buf = [0; 72];
416424
let mut end = false;
417-
loop {
418-
match seq.next_element()? {
419-
Some(0) => end = true,
420-
Some(x) if !end => v.push(x),
421-
Some(_) => {}
422-
None => break,
425+
let mut idx = 0;
426+
while let Some(x) = seq.next_element()? {
427+
if idx >= 72 {
428+
break;
429+
}
430+
if x == 0 {
431+
end = true;
432+
}
433+
if !end {
434+
v.push(x);
423435
}
424-
}
425436

426-
Ok(PartitionName(String::from_utf16_lossy(&v)))
437+
raw_buf[idx..=idx + 1].copy_from_slice(&x.to_le_bytes());
438+
idx += 2;
439+
}
440+
Ok(PartitionName(String::from_utf16_lossy(&v), raw_buf))
427441
}
428442
}
429443

@@ -441,9 +455,9 @@ impl Serialize for PartitionName {
441455
where
442456
S: Serializer,
443457
{
444-
let s = self.0.encode_utf16();
445-
let mut seq = serializer.serialize_tuple(36)?;
446-
for x in s.chain([0].iter().cycle().cloned()).take(36) {
458+
// Use the content in the raw buffer.
459+
let mut seq = serializer.serialize_tuple(72)?;
460+
for x in self.1.into_iter().take(72) {
447461
seq.serialize_element(&x)?;
448462
}
449463
seq.end()

0 commit comments

Comments
 (0)