#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use aegis_hwsim::persona::Dmi;
use aegis_hwsim::smbios::{smbios_argv, SmbiosError};
const SEED: u64 = 0xDEAD_BEEF_CAFE_BABE;
const ITERS: usize = 10_000;
struct Rng {
state: u64,
}
impl Rng {
fn new(seed: u64) -> Self {
Self { state: seed }
}
fn next_u64(&mut self) -> u64 {
let mut x = self.state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.state = x;
x.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
fn range(&mut self, n: usize) -> usize {
#[allow(clippy::cast_possible_truncation)]
let v = self.next_u64() as usize;
v % n
}
}
fn char_palette() -> Vec<&'static str> {
vec![
"A",
"Z",
"m",
"0",
"9",
" ",
"-",
"_",
".",
"(",
")",
";",
"|",
"&",
"`",
"$",
"(",
")",
"\\",
"'",
"\"",
"*",
"?",
"#",
"!",
"~",
"$(",
",",
",,",
"=",
"\t",
"\n",
"\r",
"\u{202e}",
"\u{200d}",
"\u{feff}",
"é",
"漢",
"🚀",
"/",
"..",
"../../etc/passwd",
"\0",
]
}
fn random_input(rng: &mut Rng, palette: &[&'static str]) -> String {
let len = (rng.range(32)).max(1);
let mut out = String::with_capacity(len * 4);
for _ in 0..len {
out.push_str(palette[rng.range(palette.len())]);
}
out
}
fn dmi_with_field(field: &str, value: &str) -> Dmi {
let mut d = Dmi {
sys_vendor: "QEMU".into(),
product_name: "Standard PC".into(),
product_version: None,
bios_vendor: "EDK II".into(),
bios_version: "edk2-stable".into(),
bios_date: "01/01/2024".into(),
board_name: None,
chassis_type: None,
};
match field {
"sys_vendor" => d.sys_vendor = value.to_string(),
"product_name" => d.product_name = value.to_string(),
"bios_vendor" => d.bios_vendor = value.to_string(),
"bios_version" => d.bios_version = value.to_string(),
"bios_date" => d.bios_date = value.to_string(),
"product_version" => d.product_version = Some(value.to_string()),
"board_name" => d.board_name = Some(value.to_string()),
_ => panic!("unknown field {field}"),
}
d
}
fn assert_contract(field_label: &str, value: &str, field_key: &str) {
let dmi = dmi_with_field(field_label, value);
let result = smbios_argv(&dmi);
let has_nul = value.contains('\0');
match result {
Ok(argv) => {
assert!(
!has_nul,
"NUL in {field_label} value {value:?} should have been rejected but got argv"
);
let needle = value.replace(',', ",,");
let found = argv.iter().any(|a| a.contains(&needle));
assert!(
found,
"escaped value {needle:?} not found in argv for {field_label}={value:?}: \
argv={argv:?}"
);
}
Err(SmbiosError::NulByte { field: got_field }) => {
assert!(
has_nul,
"non-NUL input was rejected as NulByte for {field_label}={value:?}"
);
assert_eq!(
got_field, field_key,
"NulByte reported wrong field: expected {field_key}, got {got_field}"
);
}
}
}
#[test]
fn fuzz_sys_vendor_preserves_argv_contract() {
let mut rng = Rng::new(SEED);
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("sys_vendor", &v, "sys_vendor");
}
}
#[test]
fn fuzz_product_name_preserves_argv_contract() {
let mut rng = Rng::new(SEED.wrapping_add(1));
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("product_name", &v, "product_name");
}
}
#[test]
fn fuzz_bios_vendor_preserves_argv_contract() {
let mut rng = Rng::new(SEED.wrapping_add(2));
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("bios_vendor", &v, "bios_vendor");
}
}
#[test]
fn fuzz_bios_version_preserves_argv_contract() {
let mut rng = Rng::new(SEED.wrapping_add(3));
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("bios_version", &v, "bios_version");
}
}
#[test]
fn fuzz_product_version_optional_field_contract() {
let mut rng = Rng::new(SEED.wrapping_add(4));
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("product_version", &v, "product_version");
}
}
#[test]
fn fuzz_board_name_optional_field_contract() {
let mut rng = Rng::new(SEED.wrapping_add(5));
let palette = char_palette();
for _ in 0..ITERS {
let v = random_input(&mut rng, &palette);
assert_contract("board_name", &v, "board_name");
}
}
#[test]
fn regression_dollar_paren_substitution_is_literal() {
let dmi = dmi_with_field("product_name", "$(whoami)");
let argv = smbios_argv(&dmi).unwrap();
assert!(argv.iter().any(|a| a.contains("$(whoami)")));
}
#[test]
fn regression_rtl_override_passes_through_literal() {
let dmi = dmi_with_field("product_name", "\u{202e}evilname");
let argv = smbios_argv(&dmi).unwrap();
assert!(argv.iter().any(|a| a.contains("\u{202e}evilname")));
}
#[test]
fn regression_repeated_commas_escape_correctly() {
let dmi = dmi_with_field("product_name", "a,b,c,d");
let argv = smbios_argv(&dmi).unwrap();
let t1 = argv
.iter()
.find(|a| a.starts_with("type=1,"))
.expect("type=1");
assert!(t1.contains("product=a,,b,,c,,d"));
}
#[test]
fn regression_nul_in_optional_field_still_names_the_field() {
let dmi = dmi_with_field("board_name", "x\0y");
let err = smbios_argv(&dmi).unwrap_err();
match err {
SmbiosError::NulByte { field } => assert_eq!(field, "board_name"),
}
}