use crate::c2pa_formats::{extract_manifest, AssetFormat};
struct Rng(u64);
impl Rng {
fn next(&mut self) -> u64 {
let mut x = self.0;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
self.0 = x;
x.wrapping_mul(0x2545F4914F6CDD1D)
}
fn bytes(&mut self, len: usize) -> Vec<u8> {
let mut v = Vec::with_capacity(len);
while v.len() < len {
v.extend_from_slice(&self.next().to_le_bytes());
}
v.truncate(len);
v
}
}
const FORMATS: &[AssetFormat] = &[
AssetFormat::Jpeg,
AssetFormat::Png,
AssetFormat::Bmff,
AssetFormat::Riff,
AssetFormat::Tiff,
AssetFormat::Gif,
AssetFormat::Svg,
AssetFormat::Pdf,
AssetFormat::Zip,
AssetFormat::Id3,
AssetFormat::Flac,
AssetFormat::Ogg,
AssetFormat::Font,
AssetFormat::Jxl,
];
const MAGICS: &[&[u8]] = &[
&[0xFF, 0xD8, 0xFF], b"\x89PNG\r\n\x1a\n", b"RIFF", b"II*\x00", b"MM\x00*", b"GIF89a", b"<?xml version=\"1.0\"?><svg", b"%PDF-1.7", b"PK\x03\x04", b"ID3\x04\x00", b"fLaC", b"OggS", b"\x00\x01\x00\x00", b"\x00\x00\x00\x0cJXL \r\n\x87\n", b"\x00\x00\x00\x18ftypisom", ];
#[test]
fn parsers_never_panic_on_random_bytes() {
let mut rng = Rng(0x9E3779B97F4A7C15);
for &fmt in FORMATS {
for _ in 0..200 {
let len = (rng.next() % 4096) as usize;
let data = rng.bytes(len);
let _ = extract_manifest(fmt, &data);
}
}
}
#[test]
fn parsers_never_panic_on_magic_prefixed_garbage() {
let mut rng = Rng(0xDEADBEEFCAFEF00D);
for &fmt in FORMATS {
for magic in MAGICS {
for _ in 0..50 {
let mut data = magic.to_vec();
let tail = (rng.next() % 2048) as usize;
data.extend(rng.bytes(tail));
let _ = extract_manifest(fmt, &data);
}
}
}
}
#[test]
fn parsers_never_panic_on_hostile_lengths() {
let cases: &[Vec<u8>] = &[
vec![0xFF, 0xFF, 0xFF, 0xFF, b'u', b'u', b'i', b'd'],
vec![
0, 0, 0, 1, b'm', b'd', b'a', b't', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
],
{
let mut v = b"\x89PNG\r\n\x1a\n".to_vec();
v.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]); v.extend_from_slice(b"caBX");
v
},
{
let mut v = b"RIFF".to_vec();
v.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]);
v.extend_from_slice(b"WEBP");
v
},
vec![0xFF, 0xD8, 0xFF, 0xEB, 0xFF, 0xFF],
vec![],
vec![0x00],
];
for &fmt in FORMATS {
for c in cases {
let _ = extract_manifest(fmt, c);
}
}
}