abhigyanpatwari/GitNexus · warning
[cfg] lang=${provider.language}: ${cdgSkippedUnsound} functi
Error message
[cfg] lang=${provider.language}: ${cdgSkippedUnsound} function(s) had control dependence skipped (EXIT not reverse-reachable from all blocks); CFG and REACHING_DEF are unaffected What it means
R8 (#2195): when building control dependence (CDG), a function whose EXIT block is not reverse-reachable from every block — an unmodeled non-terminating or multi-terminal CFG shape the synthetic-escape pass could not bridge — gets NO control dependence at all. The skip is surfaced unconditionally per language aggregate; CFG and REACHING_DEF do not depend on post-dominance and remain intact.
Source
Thrown at gitnexus/src/core/ingestion/scope-resolution/pipeline/run.ts:1581
? `; taint: ${taintTotals.findings} TAINTED, ${taintTotals.kills} SANITIZES ` +
`(${taintTotals.analyzed} function(s) analyzed, ` +
`${taintTotals.noMatch} skipped: no source/sink match` +
(taintTotals.hopsTruncated > 0
? `, ${taintTotals.hopsTruncated} finding(s) with truncated hop paths`
: '') +
`)`
: ''),
);
}
// R8 (#2195): CDG soundness skips surface UNCONDITIONALLY (parity with the
// taint/RD gap warns) — not buried in the logger.debug stats line above. A
// function whose EXIT is not reverse-reachable from every block gets NO
// control dependence (an unmodeled non-terminating / multi-terminal CFG
// shape the synthetic-escape pass could not bridge). Withholding CDG
// silently would let a language's control dependence erode unnoticed; CFG
// and REACHING_DEF do not depend on post-dominance and are unaffected.
if (cdgSkippedUnsound > 0) {
logger.warn(
`[cfg] lang=${provider.language}: ${cdgSkippedUnsound} function(s) had control ` +
`dependence skipped (EXIT not reverse-reachable from all blocks); ` +
`CFG and REACHING_DEF are unaffected`,
);
}
// R4: taint coverage gaps and cap drops surface UNCONDITIONALLY (never
// logger.debug, never input.onWarn) at the per-language aggregate, with
// counts and up to 5 example functions. Per-function warns above cover
// the rare/actionable cases (unsafe sites, cap drops); solver-status gaps
// were already per-function-warned by the RD layer (same solver, same
// fact cap), so this aggregate is their single taint-side surface.
if (taintSpec !== undefined) {
const gapCount =
taintTotals.unsafeSites +
taintTotals.gapTruncated +
taintTotals.gapOverflow +
taintTotals.gapNoFacts;
if (gapCount > 0 || taintTotals.dropped > 0) {View on GitHub (pinned to 0d1aed942f)
Solutions
- Confirm scope: only CDG is missing — CFG and REACHING_DEF queries for those functions still answer, so most flows keep working
- Locate the functions: the count is aggregate, so correlate with per-function diagnostics or query pdg_query controls on suspects to find which lost CDG
- If the shape is your own code (an intentional forever-loop), add an explicit exit path/return so EXIT becomes reverse-reachable and CDG is rebuilt
- If the shape looks normal, report it upstream as a CFG-shape modeling gap with the function source
Example fix
# before
async function pump() {
while (true) {
await tick(); // EXIT not reverse-reachable → CDG skipped for this fn
}
}
# after
async function pump(stop: () => boolean) {
while (!stop()) {
await tick(); // reachable EXIT → control dependence emitted
}
} Defensive patterns
Strategy: validation
Validate before calling
// Detect CDG loss before relying on 'controls' queries:
const res = await pdgQuery({ mode: 'controls', target: 'src/worker.ts:pump' });
if (res.results.length === 0 && analyzeLog.includes('control dependence skipped')) {
// CFG/RD still valid; only control-dependence questions are unanswerable
console.warn('CDG unavailable for pump — do not treat as no-controls');
} Prevention
- Give long-running loops an explicit exit path so EXIT stays reverse-reachable
- When pdg_query controls is empty, check the aggregate warn first — absence of CDG is not absence of control
- Track the per-function skip count across runs; growth signals new pathological CFG shapes entering the codebase
When it happens
Trigger: Running analyze with the PDG layer enabled on code containing functions with pathological terminal shapes (e.g. infinite loops with no path to EXIT, unusual multi-exit structures). cdgSkippedUnsound accumulates across those functions and the warn fires at the per-language aggregate.
Common situations: Embedded/event-loop style code with intentional infinite loops, generated state machines with unreachable exits, or languages whose CFG construction yields blocks that cannot reach EXIT. Users notice it when pdg_query mode 'controls' returns nothing for a function while CFG/RD queries still work.
Related errors
- [cfg] ${pf.filePath}: skipped ${cfgs.length - wellFormed.len
- [taint] lang=${provider.language}: ${parts.join('; ')}
- PdgEmitSink: ${errors.length} streamed CSV writer(s) hit an
- [cfg] C# buildFunctionCfg skipped a function in ${filePath}:
- [cfg] Dart buildFunctionCfg skipped a function in ${filePath
AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-08-20).
Data as JSON: /api/errors/fc23d44bbe347a91.
Report an issue: GitHub.