Skip to content

Commit 2cf6266

Browse files
authored
Merge pull request #172 from A0lson/cstring
multiboot2: Follow C behavior for string parsing
2 parents 6e76ffb + 88cac4e commit 2cf6266

File tree

1 file changed

+13
-18
lines changed

1 file changed

+13
-18
lines changed

multiboot2/src/tag.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,17 @@ impl Tag {
4343
/// UTF-8 Rust string slice without a terminating null byte or an error is
4444
/// returned.
4545
pub fn get_dst_str_slice(bytes: &[u8]) -> Result<&str, Utf8Error> {
46-
if bytes.is_empty() {
47-
// Very unlikely. A sane bootloader would omit the tag in this case.
48-
// But better be safe.
49-
return Ok("");
50-
}
46+
// Determine length of string before first NUL character
47+
48+
let length = match bytes.iter().position(|ch| (*ch) == 0x00) {
49+
// Unterminated string case:
50+
None => bytes.len(),
5151

52-
// Return without a trailing null byte. By spec, the null byte should
53-
// always terminate the string. However, for safety, we do make an extra
54-
// check.
55-
let str_slice = if bytes.ends_with(&[b'\0']) {
56-
let str_len = bytes.len() - 1;
57-
&bytes[0..str_len]
58-
} else {
59-
// Unlikely that a bootloader doesn't follow the spec and does not
60-
// add a terminating null byte.
61-
bytes
52+
// Terminated case:
53+
Some(idx) => idx,
6254
};
63-
core::str::from_utf8(str_slice)
55+
// Convert to Rust string:
56+
core::str::from_utf8(&bytes[..length])
6457
}
6558
}
6659

@@ -141,9 +134,11 @@ mod tests {
141134
// also unlikely case
142135
assert_eq!(Ok(""), Tag::get_dst_str_slice(&[b'\0']));
143136
// unlikely case: missing null byte. but the lib can cope with that
144-
assert_eq!(Ok("foobar"), Tag::get_dst_str_slice("foobar".as_bytes()));
137+
assert_eq!(Ok("foobar"), Tag::get_dst_str_slice(b"foobar"));
145138
// test that the null bytes is not included in the string slice
146-
assert_eq!(Ok("foobar"), Tag::get_dst_str_slice("foobar\0".as_bytes()));
139+
assert_eq!(Ok("foobar"), Tag::get_dst_str_slice(b"foobar\0"));
140+
// test that C-style null string termination works as expected
141+
assert_eq!(Ok("foo"), Tag::get_dst_str_slice(b"foo\0bar"));
147142
// test invalid utf8
148143
assert!(matches!(
149144
Tag::get_dst_str_slice(&[0xff, 0xff]),

0 commit comments

Comments
 (0)