use antigen::{antigen, presents};
#[antigen(
name = "size-of-in-element-count",
category = AntigenCategory::FunctionalCorrectness,
fingerprint = r#"all_of([body_calls("copy_nonoverlapping"), body_calls("size_of")])"#,
family = "numeric-truncation-overflow",
summary = "A raw-memory copy (copy_nonoverlapping) co-located with size_of — the byte-count-where-element-count foot-cannon (n * size_of as a count arg → OOB).",
references = ["https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count"],
)]
pub struct SizeOfInElementCount;
fn copy_nonoverlapping(_src: &[u8], dst: &mut Vec<u8>, count: usize) {
dst.resize(count.min(64), 0);
}
#[presents(SizeOfInElementCount)]
fn copy_bad(src: &[u8], dst: &mut Vec<u8>, n: usize) {
copy_nonoverlapping(src, dst, n * std::mem::size_of::<u32>());
}
#[presents(SizeOfInElementCount)]
fn copy_good(src: &[u8], dst: &mut Vec<u8>, n: usize) {
copy_nonoverlapping(src, dst, n);
}
fn main() {
println!("antigen numeric-truncation example: see source for the affinity-pair.");
println!(
"Both siblings are #[presents]-marked, so audit lists both; the element-count path is spared by the FINGERPRINT (it doesn't bind). To read the bind/spare side by side, see antigen/tests/stdlib_family_fingerprints.rs."
);
let src = [1u8, 2, 3, 4];
let mut dst = Vec::new();
copy_bad(&src, &mut dst, 4);
copy_good(&src, &mut dst, 4);
}