Skip to content

Commit fd0cfd2

Browse files
committed
multiboot2: tests for parsing strings from tags
1 parent 361449c commit fd0cfd2

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

multiboot2/src/boot_loader_name.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,47 @@ impl BootLoaderNameTag {
2929
/// ```
3030
pub fn name(&self) -> Result<&str, Utf8Error> {
3131
use core::{mem, slice, str};
32+
// strlen without null byte
3233
let strlen = self.size as usize - mem::size_of::<BootLoaderNameTag>();
3334
let bytes = unsafe { slice::from_raw_parts((&self.string) as *const u8, strlen) };
3435
str::from_utf8(bytes)
3536
}
3637
}
38+
39+
#[cfg(test)]
40+
mod tests {
41+
use crate::TagType;
42+
43+
const MSG: &str = "hello";
44+
45+
/// Returns the tag structure in bytes in native endian format.
46+
fn get_bytes() -> std::vec::Vec<u8> {
47+
// size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
48+
let size = (4 + 4 + MSG.as_bytes().len() + 1) as u32;
49+
[
50+
&((TagType::BootLoaderName as u32).to_ne_bytes()),
51+
&size.to_ne_bytes(),
52+
MSG.as_bytes(),
53+
// Null Byte
54+
&[0],
55+
]
56+
.iter()
57+
.flat_map(|bytes| bytes.iter())
58+
.copied()
59+
.collect()
60+
}
61+
62+
/// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
63+
#[test]
64+
fn test_parse_str() {
65+
let tag = get_bytes();
66+
let tag = unsafe {
67+
tag.as_ptr()
68+
.cast::<super::BootLoaderNameTag>()
69+
.as_ref()
70+
.unwrap()
71+
};
72+
assert_eq!({ tag.typ }, TagType::BootLoaderName);
73+
assert_eq!(tag.name().expect("must be valid UTF-8"), MSG);
74+
}
75+
}

multiboot2/src/command_line.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::TagType;
44
use core::mem;
55
use core::slice;
6-
use core::str::Utf8Error;
6+
use core::str;
77

88
/// This tag contains the command line string.
99
///
@@ -31,9 +31,48 @@ impl CommandLineTag {
3131
/// assert_eq!("/bootarg", command_line);
3232
/// }
3333
/// ```
34-
pub fn command_line(&self) -> Result<&str, Utf8Error> {
34+
pub fn command_line(&self) -> Result<&str, str::Utf8Error> {
35+
// strlen without null byte
3536
let strlen = self.size as usize - mem::size_of::<CommandLineTag>();
3637
let bytes = unsafe { slice::from_raw_parts((&self.string) as *const u8, strlen) };
37-
core::str::from_utf8(bytes)
38+
str::from_utf8(bytes)
39+
}
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use crate::TagType;
45+
46+
const MSG: &str = "hello";
47+
48+
/// Returns the tag structure in bytes in native endian format.
49+
fn get_bytes() -> std::vec::Vec<u8> {
50+
// size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
51+
let size = (4 + 4 + MSG.as_bytes().len() + 1) as u32;
52+
[
53+
&((TagType::Cmdline as u32).to_ne_bytes()),
54+
&size.to_ne_bytes(),
55+
MSG.as_bytes(),
56+
// Null Byte
57+
&[0],
58+
]
59+
.iter()
60+
.flat_map(|bytes| bytes.iter())
61+
.copied()
62+
.collect()
63+
}
64+
65+
/// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
66+
#[test]
67+
fn test_parse_str() {
68+
let tag = get_bytes();
69+
let tag = unsafe {
70+
tag.as_ptr()
71+
.cast::<super::CommandLineTag>()
72+
.as_ref()
73+
.unwrap()
74+
};
75+
assert_eq!({ tag.typ }, TagType::Cmdline);
76+
assert_eq!(tag.command_line().expect("must be valid UTF-8"), MSG);
3877
}
3978
}

multiboot2/src/elf_sections.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ impl ElfSection {
190190
use core::{slice, str};
191191

192192
let name_ptr = unsafe { self.string_table().offset(self.get().name_index() as isize) };
193+
194+
// strlen without null byte
193195
let strlen = {
194196
let mut len = 0;
195197
while unsafe { *name_ptr.offset(len) } != 0 {

multiboot2/src/module.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ impl ModuleTag {
2525
/// will return `--test cmdline-option`.
2626
pub fn cmdline(&self) -> Result<&str, Utf8Error> {
2727
use core::{mem, slice, str};
28+
// strlen without null byte
2829
let strlen = self.size as usize - mem::size_of::<ModuleTag>();
2930
let bytes = unsafe { slice::from_raw_parts((&self.cmdline_str) as *const u8, strlen) };
3031
str::from_utf8(bytes)
@@ -88,3 +89,39 @@ impl<'a> Debug for ModuleIter<'a> {
8889
list.finish()
8990
}
9091
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use crate::TagType;
96+
97+
const MSG: &str = "hello";
98+
99+
/// Returns the tag structure in bytes in native endian format.
100+
fn get_bytes() -> std::vec::Vec<u8> {
101+
// size is: 4 bytes for tag + 4 bytes for size + length of null-terminated string
102+
// 4 bytes mod_start + 4 bytes mod_end
103+
let size = (4 + 4 + 4 + 4 + MSG.as_bytes().len() + 1) as u32;
104+
[
105+
&((TagType::Module as u32).to_ne_bytes()),
106+
&size.to_ne_bytes(),
107+
&0_u32.to_ne_bytes(),
108+
&0_u32.to_ne_bytes(),
109+
MSG.as_bytes(),
110+
// Null Byte
111+
&[0],
112+
]
113+
.iter()
114+
.flat_map(|bytes| bytes.iter())
115+
.copied()
116+
.collect()
117+
}
118+
119+
/// Tests to parse a string with a terminating null byte from the tag (as the spec defines).
120+
#[test]
121+
fn test_parse_str() {
122+
let tag = get_bytes();
123+
let tag = unsafe { tag.as_ptr().cast::<super::ModuleTag>().as_ref().unwrap() };
124+
assert_eq!({ tag.typ }, TagType::Module);
125+
assert_eq!(tag.cmdline().expect("must be valid UTF-8"), MSG);
126+
}
127+
}

0 commit comments

Comments
 (0)