pub mod blockheader;
pub mod commonheader;
pub mod firstheader;
pub use blockheader::{BLOCKS_NUM, BlockHeader, BlockType};
pub use commonheader::CommonHeader;
pub use firstheader::FirstHeader;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NsisVersionHint {
Nsis1x,
Nsis2x,
Nsis3x,
Park,
Unknown,
}
pub fn scan_for_first_header(overlay: &[u8]) -> Result<(usize, FirstHeader<'_>), Error> {
let mut offset: usize = 0;
while let Some(slice) = overlay.get(offset..) {
if slice.len() < FirstHeader::SIZE {
break;
}
if let Ok(fh) = FirstHeader::parse(slice) {
return Ok((offset, fh));
}
let Some(next) = offset.checked_add(512) else {
break;
};
offset = next;
}
Err(Error::SignatureNotFound)
}
#[cfg(test)]
mod tests {
use super::*;
fn make_first_header(flags: u32) -> [u8; 28] {
let mut buf = [0u8; 28];
buf[0..4].copy_from_slice(&flags.to_le_bytes());
buf[4..8].copy_from_slice(&0xDEADBEEFu32.to_le_bytes());
buf[8..12].copy_from_slice(&0x6C6C754Eu32.to_le_bytes()); buf[12..16].copy_from_slice(&0x74666F73u32.to_le_bytes()); buf[16..20].copy_from_slice(&0x74736E49u32.to_le_bytes()); buf[20..24].copy_from_slice(&1024i32.to_le_bytes()); buf[24..28].copy_from_slice(&2048i32.to_le_bytes()); buf
}
#[test]
fn scan_finds_header_at_offset_zero() {
let fh = make_first_header(0);
let mut overlay = vec![0u8; 1024];
overlay[..28].copy_from_slice(&fh);
let (off, _hdr) = scan_for_first_header(&overlay).unwrap();
assert_eq!(off, 0);
}
#[test]
fn scan_finds_header_at_512() {
let fh = make_first_header(0);
let mut overlay = vec![0u8; 2048];
overlay[512..512 + 28].copy_from_slice(&fh);
let (off, _hdr) = scan_for_first_header(&overlay).unwrap();
assert_eq!(off, 512);
}
#[test]
fn scan_finds_header_at_1024() {
let fh = make_first_header(0x01); let mut overlay = vec![0u8; 2048];
overlay[1024..1024 + 28].copy_from_slice(&fh);
let (off, hdr) = scan_for_first_header(&overlay).unwrap();
assert_eq!(off, 1024);
assert!(hdr.is_uninstaller());
}
#[test]
fn scan_fails_on_empty_overlay() {
let overlay = vec![0u8; 512];
assert_eq!(
scan_for_first_header(&overlay),
Err(Error::SignatureNotFound)
);
}
#[test]
fn scan_fails_on_non_aligned_header() {
let fh = make_first_header(0);
let mut overlay = vec![0u8; 2048];
overlay[256..256 + 28].copy_from_slice(&fh);
assert_eq!(
scan_for_first_header(&overlay),
Err(Error::SignatureNotFound)
);
}
}