Skip to content

Commit 88cac4e

Browse files
A0lsonphip1611
authored andcommitted
multiboot2: Follow C behavior for string parsing
The various strings in the Multiboot2 spec are specified as C-style zero-terminated strings. Previously, if the multiboot2 crate is handed a string with non-NUL characters present between the terminating NUL (within the tag), they were returned as well. This revision instead terminates the strings on the first NUL character, as would be typical in C handling. Although unterminated strings in Multiboot2 are technically an error, current unterminated string behavior is maintained.
1 parent 6e76ffb commit 88cac4e

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)