#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Executable {
Pe,
Elf,
MachO,
Script,
}
impl Executable {
#[must_use]
pub fn describes(self) -> &'static str {
match self {
Self::Pe => "a Windows executable",
Self::Elf => "a Linux executable",
Self::MachO => "a macOS executable",
Self::Script => "a script",
}
}
}
pub const HEAD: usize = 4;
#[must_use]
pub fn executable(head: &[u8]) -> Option<Executable> {
match head {
[b'M', b'Z', ..] => Some(Executable::Pe),
[0x7f, b'E', b'L', b'F', ..] => Some(Executable::Elf),
[0xfe, 0xed, 0xfa, 0xce | 0xcf, ..] | [0xce | 0xcf, 0xfa, 0xed, 0xfe, ..] => {
Some(Executable::MachO)
}
[b'#', b'!', ..] => Some(Executable::Script),
_ => None,
}
}
#[must_use]
pub fn misrepresents(head: &[u8], policy_key: Option<&str>) -> Option<Executable> {
let what = executable(head)?;
match policy_key {
Some(k) if EXPECTED.contains(&k) => None,
_ => Some(what),
}
}
const EXPECTED: &[&str] = &[
"exe", "dll", "com", "scr", "sys", "cpl", "ocx", "drv", "efi", "so", "o", "a", "bin", "elf", "ko", "dylib", "bundle", "sh", "bash", "zsh", "csh", "ksh", "fish", "py", "pl", "rb", "lua", "tcl", "awk", "sed", "r",
"ps1",
];
#[cfg(test)]
mod tests {
use super::{executable, misrepresents, Executable};
#[test]
fn recognises_the_four_things_that_run() {
assert_eq!(executable(b"MZ\x90\x00"), Some(Executable::Pe));
assert_eq!(executable(b"\x7fELF"), Some(Executable::Elf));
assert_eq!(executable(b"\xcf\xfa\xed\xfe"), Some(Executable::MachO));
assert_eq!(executable(b"#!/bin/sh"), Some(Executable::Script));
}
#[test]
fn mach_o_is_recognised_in_both_orders_and_both_widths() {
for magic in [
b"\xfe\xed\xfa\xce",
b"\xce\xfa\xed\xfe",
b"\xfe\xed\xfa\xcf",
b"\xcf\xfa\xed\xfe",
] {
assert_eq!(executable(magic), Some(Executable::MachO), "{magic:x?}");
}
}
#[test]
fn a_universal_binary_is_not_reported() {
assert_eq!(executable(b"\xca\xfe\xba\xbe"), None);
}
#[test]
fn a_pdf_is_not_something_that_runs() {
assert_eq!(executable(b"%PDF"), None);
}
#[test]
fn a_zip_is_not_something_that_runs() {
assert_eq!(executable(b"PK\x03\x04"), None);
}
#[test]
fn short_input_answers_rather_than_panicking() {
assert_eq!(executable(b""), None);
assert_eq!(executable(b"M"), None);
assert_eq!(executable(b"\x7fEL"), None);
assert_eq!(executable(b"#!"), Some(Executable::Script));
}
#[test]
fn an_executable_wearing_a_documents_name_is_reported() {
assert_eq!(
misrepresents(b"MZ\x90\x00", Some("pdf")),
Some(Executable::Pe)
);
}
#[test]
fn an_executable_wearing_its_own_name_is_not() {
assert_eq!(misrepresents(b"MZ\x90\x00", Some("exe")), None);
assert_eq!(misrepresents(b"\x7fELF", Some("so")), None);
assert_eq!(misrepresents(b"#!/bin/sh", Some("sh")), None);
}
#[test]
fn a_document_is_never_reported_whatever_it_is_called() {
assert_eq!(misrepresents(b"%PDF", Some("pdf")), None);
assert_eq!(misrepresents(b"%PDF", Some("exe")), None);
assert_eq!(misrepresents(b"PK\x03\x04", Some("docx")), None);
}
#[test]
fn an_extension_too_exotic_to_fold_does_not_suppress_the_report() {
assert_eq!(misrepresents(b"MZ\x90\x00", None), Some(Executable::Pe));
}
}