use antigen::{antigen, defended_by, presents};
#[antigen(
name = "panicking-in-drop",
family = "boundary-violation",
fingerprint = r#"
item = impl,
any_of([
body_contains_macro("panic"),
body_contains_macro("unreachable"),
body_contains_macro("todo"),
body_contains_macro("unimplemented")
])
"#,
summary = "Drop impls must not panic; panic-during-unwind causes process abort.",
references = [
"https://doc.rust-lang.org/std/ops/trait.Drop.html#panics",
],
)]
pub struct PanickingInDrop;
pub struct VulnerableType {
pub data: Option<String>,
}
#[presents(PanickingInDrop)]
impl Drop for VulnerableType {
fn drop(&mut self) {
let _val = self.data.as_ref().unwrap_or(&String::new()).clone();
}
}
pub struct SafeType {
pub data: Option<String>,
}
#[presents(PanickingInDrop)]
impl Drop for SafeType {
fn drop(&mut self) {
if let Some(_d) = self.data.as_ref() {
}
}
}
#[allow(dead_code)]
#[defended_by(PanickingInDrop)]
fn safe_type_drop_no_panic_test() {
let s = SafeType { data: None };
drop(s);
let s = SafeType {
data: Some(String::from("hello")),
};
drop(s);
}
fn main() {
println!("antigen example: see source for #[antigen], #[presents], #[defended_by] usage.");
println!("Run `cargo run --bin cargo-antigen -- antigen scan` to see them detected.");
let v = VulnerableType {
data: Some("data".to_string()),
};
drop(v);
let s = SafeType { data: None };
drop(s);
safe_type_drop_no_panic_test();
}