pub mod corpus;
pub use corpus::{corpus_catalogs, corpus_metadata};
pub mod builtin_drop_lsb_add;
pub mod builtin_drop_msb_not;
pub mod builtin_hardcoded_input_add;
pub mod builtin_hardcoded_zero_add;
pub mod builtin_mod_mask_shl;
pub mod builtin_nondeterministic_add;
pub mod builtin_off_by_one_add;
pub mod builtin_pseudo_correct_add;
pub mod builtin_sign_flip_negate;
pub mod builtin_swapped_operand_sub;
pub(crate) use builtin_drop_lsb_add::builtin_drop_lsb_add;
pub(crate) use builtin_hardcoded_input_add::builtin_hardcoded_input_add;
pub(crate) use builtin_hardcoded_zero_add::builtin_hardcoded_zero_add;
pub(crate) use builtin_nondeterministic_add::builtin_nondeterministic_add;
pub(crate) use builtin_off_by_one_add::builtin_off_by_one_add;
pub(crate) use builtin_pseudo_correct_add::builtin_pseudo_correct_add;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DefenderClass {
Backdoor,
DropLsb,
DropMsb,
HardcodedInput,
HardcodedZero,
ModMask,
Nondeterministic,
OffByOne,
PseudoCorrect,
SignFlip,
SwappedOperand,
Unsupported,
}
#[derive(Clone)]
pub struct Defendant {
pub id: &'static str,
pub target_op_id: &'static str,
pub description: &'static str,
pub class: DefenderClass,
pub broken_fn: fn(&[u8]) -> Vec<u8>,
pub fails_laws: &'static [&'static str],
pub expected_witness: &'static [(u32, u32)],
}
pub struct DefendantCatalog {
pub target_op_id: &'static str,
pub defendants: Vec<Defendant>,
}
#[inline]
pub(crate) fn read_binary(input: &[u8]) -> (u32, u32) {
assert!(
input.len() >= 8,
"read_binary called with {} bytes; expected at least 8 bytes",
input.len()
);
let a = u32::from_le_bytes([input[0], input[1], input[2], input[3]]);
let b = u32::from_le_bytes([input[4], input[5], input[6], input[7]]);
(a, b)
}
#[inline]
pub(crate) fn read_unary(input: &[u8]) -> u32 {
assert!(
input.len() >= 4,
"read_unary called with {} bytes; expected at least 4 bytes",
input.len()
);
u32::from_le_bytes([input[0], input[1], input[2], input[3]])
}
#[inline]
pub(crate) fn write_u32(value: u32) -> Vec<u8> {
value.to_le_bytes().to_vec()
}
#[inline]
pub(crate) fn tweak(value: u32, mode: u8) -> u32 {
let wrong = match mode % 8 {
0 => value.wrapping_add(1),
1 => value.wrapping_sub(1),
2 => value ^ 1,
3 => !value,
4 => value.rotate_left(1),
5 => value.rotate_right(1),
6 => value.wrapping_add(0x9E37_79B9),
_ => value ^ 0xA5A5_5A5A,
};
if wrong == value {
value ^ 1
} else {
wrong
}
}
#[inline]
pub(crate) fn bool_tweak(value: u32, mode: u8) -> u32 {
match mode % 5 {
0 => 1 - (value & 1),
1 => 2,
2 => u32::MAX,
3 => value ^ 1,
_ => 42,
}
}
pub mod catalogs;
pub mod macros;
pub type MutationClass = DefenderClass;
#[must_use]
pub const fn defender_class_to_spec(class: DefenderClass) -> crate::spec::types::MutationClass {
use crate::spec::types::MutationClass as C;
match class {
DefenderClass::Backdoor => C::ControlFlowMutations,
DefenderClass::DropLsb => C::BitwiseMutations,
DefenderClass::DropMsb => C::BitwiseMutations,
DefenderClass::HardcodedInput => C::BufferAccessMutations,
DefenderClass::HardcodedZero => C::ConstantMutations,
DefenderClass::ModMask => C::LoweringMutations,
DefenderClass::Nondeterministic => C::OrderingMutations,
DefenderClass::OffByOne => C::BufferAccessMutations,
DefenderClass::PseudoCorrect => C::LawMutations,
DefenderClass::SignFlip => C::ArithmeticMutations,
DefenderClass::SwappedOperand => C::ComparisonMutations,
DefenderClass::Unsupported => C::IrStructuralMutations,
}
}
#[must_use]
#[inline]
pub fn full_catalog() -> Vec<DefendantCatalog> {
let mut catalogs = catalogs::built_in_catalogs();
catalogs.extend(corpus::corpus_catalogs());
catalogs
}