2026-02-25 21:16:36 -05:00
|
|
|
use crate::evidence::Confidence;
|
|
|
|
|
use crate::patterns::{Pattern, PatternCategory, PatternTier, Severity};
|
2025-06-17 01:17:48 +02:00
|
|
|
|
2026-02-25 21:16:36 -05:00
|
|
|
/// C++ AST patterns.
|
|
|
|
|
///
|
|
|
|
|
/// Inherits C banned-function concerns plus C++-specific patterns like
|
|
|
|
|
/// `reinterpret_cast` and `const_cast`. Taint rules overlap with C rules
|
|
|
|
|
/// for `system`/`sprintf`/`strcpy`/`strcat`.
|
2025-06-17 01:17:48 +02:00
|
|
|
pub const PATTERNS: &[Pattern] = &[
|
2026-02-25 21:16:36 -05:00
|
|
|
// ── Tier A: Banned C functions (inherited) ─────────────────────────
|
2025-06-24 20:27:06 +02:00
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.memory.gets",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "gets() has no bounds checking and is always exploitable",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "gets")) @vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::High,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
|
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.memory.strcpy",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "strcpy() does not bounds-check the destination buffer",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "strcpy")) @vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::High,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
|
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.memory.strcat",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "strcat() does not bounds-check the destination buffer",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "strcat")) @vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::High,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
|
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.memory.sprintf",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "sprintf() does not limit the output buffer length",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "sprintf")) @vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::High,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
2026-02-25 21:16:36 -05:00
|
|
|
// ── Tier A: Command execution ──────────────────────────────────────
|
2025-06-24 20:27:06 +02:00
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.cmdi.system",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "system() runs a shell command",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "system")) @vuln"#,
|
|
|
|
|
severity: Severity::High,
|
|
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::CommandExec,
|
|
|
|
|
confidence: Confidence::High,
|
|
|
|
|
},
|
|
|
|
|
Pattern {
|
|
|
|
|
id: "cpp.cmdi.popen",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "popen() runs a shell command",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression function: (identifier) @id (#eq? @id "popen")) @vuln"#,
|
|
|
|
|
severity: Severity::High,
|
|
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::CommandExec,
|
|
|
|
|
confidence: Confidence::High,
|
|
|
|
|
},
|
|
|
|
|
// ── Tier A: Dangerous casts ────────────────────────────────────────
|
|
|
|
|
// C++ casts are parsed as call_expression with template_function
|
|
|
|
|
Pattern {
|
|
|
|
|
id: "cpp.memory.reinterpret_cast",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "reinterpret_cast performs a type-punning cast",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression
|
|
|
|
|
function: (template_function
|
|
|
|
|
name: (identifier) @n (#eq? @n "reinterpret_cast")))
|
|
|
|
|
@vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::Medium,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
|
|
|
|
Pattern {
|
2026-02-25 21:16:36 -05:00
|
|
|
id: "cpp.memory.const_cast",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "const_cast removes the const/volatile qualifier",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression
|
|
|
|
|
function: (template_function
|
|
|
|
|
name: (identifier) @n (#eq? @n "const_cast")))
|
|
|
|
|
@vuln"#,
|
2025-06-24 20:27:06 +02:00
|
|
|
severity: Severity::Medium,
|
2026-02-25 21:16:36 -05:00
|
|
|
tier: PatternTier::A,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::High,
|
|
|
|
|
},
|
|
|
|
|
// ── Tier B: Format-string (variable first arg) ─────────────────────
|
|
|
|
|
Pattern {
|
|
|
|
|
id: "cpp.memory.printf_no_fmt",
|
2026-04-29 00:58:38 -04:00
|
|
|
description: "printf(var) is a format-string vulnerability when the first arg is not a literal",
|
2026-02-25 21:16:36 -05:00
|
|
|
query: r#"(call_expression
|
|
|
|
|
function: (identifier) @id (#eq? @id "printf")
|
|
|
|
|
arguments: (argument_list
|
|
|
|
|
. (identifier) @arg))
|
|
|
|
|
@vuln"#,
|
|
|
|
|
severity: Severity::High,
|
|
|
|
|
tier: PatternTier::B,
|
|
|
|
|
category: PatternCategory::MemorySafety,
|
|
|
|
|
confidence: Confidence::Medium,
|
2025-06-24 20:27:06 +02:00
|
|
|
},
|
2025-06-17 01:17:48 +02:00
|
|
|
];
|