Skip to content

v0.6.1

Choose a tag to compare

@github-actions github-actions released this 18 Aug 20:31
· 9 commits to main since this release
2e0f3c2

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 add wasn'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_root wasn'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.c resolved the wrong requirements filename in some code
    paths, --sec-tested didn't gate on the real tested count, and
    Metric 1 could disagree with the underlying data.
    Canonical
    .fusa-reqs.json resolution with legacy fallback; a real
    --sec-tested gate. (#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's strncpy could leave an unterminated buffer; L002 only matched
    goto when 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 and cfusa_config_is_excluded() matched
    substrings without boundary checks
    , e.g. excluding src/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.c had 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 —
    reordering operationalSituations/hazards/safetyGoals in 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-D silently discarded an explicit --threshold
    (zeroing it instead of leaving it alone, asymmetric with how
    --asil QM already 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_long loops fully reset BSD's
    optreset/glibc's nextchar
    between invocations — a bare
    optind = 1 doesn'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 hardcoded return 0
    regardless of findings added,
    breaking the run()-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 build

Verify

cfusa version
cfusa qualify

What'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