capa-rs parses untrusted input (both rule YAML and binaries), but several sites panic or abort the whole analysis on malformed data instead of returning an error or skipping the bad item. Found by code review on master (0.5.2); each has a regression test in the linked PR.
Panics on malformed rule YAML
number/ / offset/ with an empty or missing bitness suffix — src/rules/mod.rs:478,483: &parts[1].trim()[1..] slices out of bounds when the suffix is empty (number/). The documented form is number/x32 (capa-rules doc/format.md), so stripping the first byte is intended for the x — but nothing validates it, and an over-u32 suffix silently truncates via as u32.
string: / or string: /i — src/rules/features.rs:1318,1329: &value[1..value.len()-1] is [1..0] for a bare / → slice panic. StringFactory accepts it (starts+ends with /), the panic happens in RegexFeature::new.
- Negative count wraps to
u32::MAX — src/rules/mod.rs:1056-1063: count(api(x)): -1 in YAML hits *i as u32 → 4294967295. The string forms were hardened in 0.4.2 (parse_count_u32), the integer arm was missed.
- Public
topologically_order_rules panics on a missing dependency — src/rules/mod.rs:1841: rules_by_name[&dep] indexes the map directly.
Panics / aborts on malformed binaries
- One bad instruction kills the whole file —
src/lib.rs:1041: extractor.extract_insn_features(f, insn)? propagates any per-instruction error up through the rayon loop, aborting analysis of the entire binary. Should be best-effort: log and skip the instruction.
detect_ascii_len errors on a string ending exactly at end of buffer — src/extractor/smda.rs:1678: a printable string at EOF with no trailing NUL is treated as "buffer overflow" and (via ? in read_string) aborts feature extraction for that instruction. read_bytes already clamps; returning the length is enough.
read_bytes underflows when offset < base_addr — src/extractor/smda.rs:1626 (offset - report.base_addr without checked_sub; sibling detect_ascii_len already does the checked version).
is_security_cookie panics on single-operand formatting — src/extractor/smda.rs:1727: operands[1] when format_operands produced no comma.
- .NET extractor panics on empty method bodies and null tokens —
src/extractor/dnfile.rs:106 (instructions[0] on an empty body) and src/extractor/dnfile.rs:1276 (t.rid() - 1 underflow when rid == 0).
Smaller correctness fixes in the same area
count(mnemonic(mov) (missing closing paren) silently mangles the argument to mo — src/rules/mod.rs:1028-1036.
- Inline descriptions split on every
" = " instead of the first, losing the tail — src/rules/mod.rs:543-551 → splitn(2, …).
PR with fixes + regression tests follows.
capa-rs parses untrusted input (both rule YAML and binaries), but several sites panic or abort the whole analysis on malformed data instead of returning an error or skipping the bad item. Found by code review on master (0.5.2); each has a regression test in the linked PR.
Panics on malformed rule YAML
number//offset/with an empty or missing bitness suffix —src/rules/mod.rs:478,483:&parts[1].trim()[1..]slices out of bounds when the suffix is empty (number/). The documented form isnumber/x32(capa-rulesdoc/format.md), so stripping the first byte is intended for thex— but nothing validates it, and an over-u32suffix silently truncates viaas u32.string: /orstring: /i—src/rules/features.rs:1318,1329:&value[1..value.len()-1]is[1..0]for a bare/→ slice panic.StringFactoryaccepts it (starts+ends with/), the panic happens inRegexFeature::new.u32::MAX—src/rules/mod.rs:1056-1063:count(api(x)): -1in YAML hits*i as u32→ 4294967295. The string forms were hardened in 0.4.2 (parse_count_u32), the integer arm was missed.topologically_order_rulespanics on a missing dependency —src/rules/mod.rs:1841:rules_by_name[&dep]indexes the map directly.Panics / aborts on malformed binaries
src/lib.rs:1041:extractor.extract_insn_features(f, insn)?propagates any per-instruction error up through the rayon loop, aborting analysis of the entire binary. Should be best-effort: log and skip the instruction.detect_ascii_lenerrors on a string ending exactly at end of buffer —src/extractor/smda.rs:1678: a printable string at EOF with no trailing NUL is treated as "buffer overflow" and (via?inread_string) aborts feature extraction for that instruction.read_bytesalready clamps; returning the length is enough.read_bytesunderflows whenoffset < base_addr—src/extractor/smda.rs:1626(offset - report.base_addrwithoutchecked_sub; siblingdetect_ascii_lenalready does the checked version).is_security_cookiepanics on single-operand formatting —src/extractor/smda.rs:1727:operands[1]whenformat_operandsproduced no comma.src/extractor/dnfile.rs:106(instructions[0]on an empty body) andsrc/extractor/dnfile.rs:1276(t.rid() - 1underflow when rid == 0).Smaller correctness fixes in the same area
count(mnemonic(mov)(missing closing paren) silently mangles the argument tomo—src/rules/mod.rs:1028-1036." = "instead of the first, losing the tail —src/rules/mod.rs:543-551→splitn(2, …).PR with fixes + regression tests follows.