Skip to content

Commit 11dcb4f

Browse files
committed
cstr16: add from_u8_with_nul
1 parent 83a0032 commit 11dcb4f

File tree

3 files changed

+33
-8
lines changed

3 files changed

+33
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- `DevicePath::to_boxed`, `DevicePath::to_owned`, and `DevicePath::as_bytes`
77
- `DevicePathInstance::to_boxed`, `DevicePathInstance::to_owned`, and `DevicePathInstance::as_bytes`
88
- `DevicePathNode::data`
9+
- `CStr16::from_u8_with_nul`.
910

1011
### Changed
1112

uefi-test-runner/src/boot/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ fn test_load_image(bt: &BootServices) {
6565
node.device_type() == DeviceType::MEDIA /* 0x4 */
6666
&& node.sub_type() == DeviceSubType::HARDWARE_VENDOR /* 0x4 */
6767
})
68-
.map(|node| unsafe { CStr16::from_ptr(node.data().as_ptr().cast()) })
68+
.map(|node| CStr16::from_u8_with_nul(node.data()).expect("should be valid CCtr16"))
6969
// to Rust string
7070
.map(|cstr16| cstr16.to_string().to_uppercase())
7171
.expect("should have file-path portion in device path");

uefi/src/data_types/strs.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ pub enum FromSliceWithNulError {
2222

2323
/// The slice was not null-terminated
2424
NotNulTerminated,
25+
26+
/// The buffer is broken. For example, not a multiple of 2 bytes.
27+
BrokenBuffer,
2528
}
2629

2730
/// Error returned by [`CStr16::from_unaligned_slice`].
@@ -211,10 +214,21 @@ impl CStr16 {
211214
Self::from_u16_with_nul_unchecked(slice::from_raw_parts(ptr, len + 1))
212215
}
213216

214-
/// Creates a C string wrapper from a u16 slice
215-
///
216-
/// Since not every u16 value is a valid UCS-2 code point, this function
217-
/// must do a bit more validity checking than CStr::from_bytes_with_nul
217+
/// Creates a `&CStr16` from a u8 slice, if the slice contains exactly
218+
/// one terminating null-byte and all chars are valid UCS-2 chars.
219+
pub fn from_u8_with_nul(slice: &[u8]) -> Result<&Self, FromSliceWithNulError> {
220+
if slice.is_empty() {
221+
return Err(FromSliceWithNulError::NotNulTerminated);
222+
}
223+
if slice.len() % 2 != 0 {
224+
return Err(FromSliceWithNulError::BrokenBuffer);
225+
}
226+
let slice = unsafe { slice::from_raw_parts(slice.as_ptr().cast::<u16>(), slice.len() / 2) };
227+
Self::from_u16_with_nul(slice)
228+
}
229+
230+
/// Creates a `&CStr16` from a u16 slice, if the slice contains exactly
231+
/// one terminating null-byte and all chars are valid UCS-2 chars.
218232
pub fn from_u16_with_nul(codes: &[u16]) -> Result<&Self, FromSliceWithNulError> {
219233
for (pos, &code) in codes.iter().enumerate() {
220234
match code.try_into() {
@@ -234,7 +248,7 @@ impl CStr16 {
234248
Err(FromSliceWithNulError::NotNulTerminated)
235249
}
236250

237-
/// Unsafely creates a C string wrapper from a u16 slice.
251+
/// Unsafely creates a `&CStr16` from a u16 slice.
238252
///
239253
/// # Safety
240254
///
@@ -287,11 +301,13 @@ impl CStr16 {
287301
Self::from_u16_with_nul(&buf[..index + 1]).map_err(|err| match err {
288302
FromSliceWithNulError::InvalidChar(p) => FromStrWithBufError::InvalidChar(p),
289303
FromSliceWithNulError::InteriorNul(p) => FromStrWithBufError::InteriorNul(p),
290-
FromSliceWithNulError::NotNulTerminated => unreachable!(),
304+
FromSliceWithNulError::NotNulTerminated | FromSliceWithNulError::BrokenBuffer => {
305+
unreachable!()
306+
}
291307
})
292308
}
293309

294-
/// Create a [`CStr16`] from an [`UnalignedSlice`] using an aligned
310+
/// Create a `&CStr16` from an [`UnalignedSlice`] using an aligned
295311
/// buffer for storage. The lifetime of the output is tied to `buf`,
296312
/// not `src`.
297313
pub fn from_unaligned_slice<'buf>(
@@ -313,6 +329,7 @@ impl CStr16 {
313329
FromSliceWithNulError::InvalidChar(v) => UnalignedCStr16Error::InvalidChar(v),
314330
FromSliceWithNulError::InteriorNul(v) => UnalignedCStr16Error::InteriorNul(v),
315331
FromSliceWithNulError::NotNulTerminated => UnalignedCStr16Error::NotNulTerminated,
332+
FromSliceWithNulError::BrokenBuffer => UnalignedCStr16Error::BufferTooSmall,
316333
})
317334
}
318335

@@ -562,6 +579,13 @@ mod tests {
562579
assert_eq!(<CStr8 as Borrow<[u8]>>::borrow(string), &[b'a', 0]);
563580
}
564581

582+
#[test]
583+
fn test_cstr16_from_slice() {
584+
let s1 = CStr16::from_u8_with_nul(&[65, 0, 66, 0, 67, 0, 0, 0]).unwrap();
585+
let s2 = CStr16::from_u16_with_nul(&[65, 66, 67, 0]).unwrap();
586+
assert_eq!(s1, s2)
587+
}
588+
565589
#[test]
566590
fn test_cstr16_num_bytes() {
567591
let s = CStr16::from_u16_with_nul(&[65, 66, 67, 0]).unwrap();

0 commit comments

Comments
 (0)