Repository navigation
v0.6.1
cfusa v0.6.1
Forty-three fixes from a 40-agent deep-audit sweep of the codebase
(#141–#182) plus one more found and fixed the same session (#187).
Patch version bump — precision/correctness fixes only, no new
user-facing flags or behaviors. Every fix ships with regression tests
verified to fail against the pre-fix code and pass against the fix;
44/44 test suites pass and the self-check is clean.
Fixed
- Disposition JSON loading was brittle to incidental whitespace
around field values in.fusa-dispositions.json/.fusa-qualitybar.json/
HARA files — replaced ad hoc field extraction with a shared
whitespace-tolerant JSON string-field helper. (#143, #159, #175, #176) cfusa disposition addwasn't atomic and could corrupt the
dispositions file under concurrent writes, and didn't handle a
bare-array file shape. Now writes via a locked, atomic
temp-file-plus-rename, with a bare-array merge fallback. (#144, #158)- DISP001 matched on a whole-file substring instead of the real
fingerprint-scoped disposition mechanism, so an unrelated finding
whose message happened to mention a disposed rule id could be wrongly
suppressed. (#148) project_rootwasn't set consistently across commands, so the
same finding could get different fingerprints depending on which
command produced it — breaking cross-command disposition matching.
(#153)cmd_req.cresolved the wrong requirements filename in some code
paths,--sec-testeddidn't gate on the real tested count, and
Metric 1 could disagree with the underlying data. Canonical
.fusa-reqs.jsonresolution with legacy fallback; a real
--sec-testedgate. (#146, #147, #166)- Five CFUSA-CY rules (CY003/CY004/CY006/CY007/CY019) matched
dangerous-function names without identifier-boundary checks,
false-positiving on any name merely containing the pattern as a
substring. Switched to a shared boundary-aware matcher
(cfusa_find_token_outside_string()). (#154, #155, #156, #157, #173) cmd_lint.c's L001/L002/L003/L006 had precision and safety gaps:
L001'sstrncpycould leave an unterminated buffer; L002 only matched
gotowhen it started the line; L003/L006 had no persistent
block-comment tracking across lines, so multi-line comments without a
leading*on continuation lines were scanned as code. (#161, #162,
#163, #177)- The legacy
REQ:scanner andcfusa_config_is_excluded()matched
substrings without boundary checks, e.g. excludingsrc/rebuild_utils.c
purely because it contains "build". Anchored to identifier/path-segment
boundaries. (#174, #180) cmd_analyze.c's A001/A003/A006/A007 had false-positive/negative
precision issues: A003 missed multi-declarator lines, A006 matched
pointer-arithmetic incorrectly, A007 missed some unchecked-fclose
sites. (#149, #150, #151, #169)- Silent-truncation trio:
cfusa coverage's lcov parser could
misread an empty/unreadable file as 100% coverage; the HLR/LLR arrays
were capped at a fixed 512 entries with no warning; HARA's nested
reference arrays silently dropped entries past their cap. All three
now fail loudly or warn instead of silently under-reporting. (#142,
#160, #167) report.chad internal-consistency and formatting gaps: the
printed Result line didn't account for--strict; summary
tables/top-rules didn't exclude dispositioned findings; JSON/CSV
output had buffer-sizing and escaping issues. A new RFC 4180 CSV
writer was added. (#164, #165, #178, #179)- A failed report write silently exited 0 instead of the documented
exit code 3. (#141) cmd_hara.c's top-level JSON parsing was key-order-dependent —
reorderingoperationalSituations/hazards/safetyGoalsin the
source file could scope a scan incorrectly. Fixed via depth-1-bounded
bracket matching that no longer depends on key order. (#145)cfusa_config_save()only persisted the first declared standard
when multiple were set via--standard a,b, silently dropping the
rest on every re-save. (#168)--dal DAL-Dsilently discarded an explicit--threshold
(zeroing it instead of leaving it alone, asymmetric with how
--asil QMalready behaves), and--dal DAL-A/--asil ASIL-D's
100%-MC/DC requirement wasn't reflected in--mcdc-threshold,
letting a weaker explicit threshold silently pass. (#152, #172)- Only 3 of the ~41 commands'
getopt_longloops fully reset BSD's
optreset/glibc'snextcharbetween invocations — a bare
optind = 1doesn't fully clear either, risking stale-state misparses
across the repeated, in-process invocation pattern this project's own
test suite (and any embedding caller) uses. Applied the full
platform-reset block to every command. (#170, #171) - COUP001's
extern-variable match was unanchored and
comment-unaware, false-positiving on prose mentioning "extern"
inside a multi-line comment continuation line; COUP001/COUP002/
COMP001 all hardcodedreturn 0regardless of findings added,
breaking therun()-returns-finding-count contract every other rule
follows. (#181, #182) - CFUSA-L004's recursion detector had no comment-awareness,
misreporting a function as recursive when a comment inside its body
merely mentioned its own name. (#187)
Installation
# Linux (amd64)
curl -Lo cfusa https://github.com/SoundMatt/c-FuSa/releases/download/v0.6.1/cfusa-linux-amd64
chmod +x cfusa && sudo mv cfusa /usr/local/bin/
# macOS (arm64)
curl -Lo cfusa https://github.com/SoundMatt/c-FuSa/releases/download/v0.6.1/cfusa-darwin-arm64
chmod +x cfusa && sudo mv cfusa /usr/local/bin/
# From source
cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --install buildVerify
cfusa version
cfusa qualifyWhat's Changed
- fix: whitespace-tolerant JSON field extraction for dispositions/qualitybar/hara by @SoundMatt in #183
- fix: atomic, race-free disposition writes + bare-array merge fallback by @SoundMatt in #184
- fix: DISP001 defers to the real fingerprint-scoped disposition mechanism by @SoundMatt in #185
- fix: set project_root consistently so fingerprints agree across commands by @SoundMatt in #186
- fix: cmd_req canonical filename + real sec-tested gate + Metric 1 consistency by @SoundMatt in #188
- fix: identifier-boundary checks across 5 cyber rules (CY003/4/6/7/19) by @SoundMatt in #189
- fix: cmd_lint.c hardening — L001/L002/L003/L006 precision + safety fixes by @SoundMatt in #190
- fix: identifier-boundary matching for legacy REQ: scanner + exclude_dirs by @SoundMatt in #191
- fix: cmd_analyze.c hardening — A001/A003/A006/A007 precision fixes by @SoundMatt in #192
- fix: silent-truncation trio — lcov coverage, HLR/LLR arrays, hara nested refs by @SoundMatt in #193
- fix: report.c consistency + buffer/format fixes (Result/SUMMARY/JSON/CSV) by @SoundMatt in #194
- fix: report-write failures now exit 3, matching the documented contract by @SoundMatt in #195
- fix: cmd_hara.c top-level parsing immune to key reordering by @SoundMatt in #196
- fix: cfusa_config_save() persists every declared standard, not just [0] by @SoundMatt in #197
- fix: coverage DAL-D discards explicit thresholds; DAL-A/ASIL-D don't floor MC/DC threshold by @SoundMatt in #198
- fix: getopt_long platform-reset sweep across all CLI commands by @SoundMatt in #199
- fix: COUP001 anchored extern match + comment-awareness; COUP001/COUP002/COMP001 return-value contract by @SoundMatt in #200
- fix: CFUSA-L004 self-call detector is comment-aware by @SoundMatt in #201
- chore: bump v0.6.0 -> v0.6.1 by @SoundMatt in #202
Full Changelog: v0.6.0...v0.6.1