mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
fix(cfg): harvest Go select channel-receive binding as a def (#2195)
walkValue had no receive_statement case, so a select receive (case v := <-ch:) fell to the default descent: v was recorded as a USE of an uninitialized var and the channel-sourced definition was invisible to REACHING_DEF/taint — channels are a primary taint source in Go. Add the case mirroring short_var_declaration: def each left identifier, use the <-ch right, attach resultDefs for the := short form. prescan already declared the binding; this completes the phase-2 fact. go:branchy bench fingerprint unchanged; go suite 40 passed, grammar gate green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
33446d61c3
commit
31936a0929
2 changed files with 22 additions and 0 deletions
|
|
@ -438,6 +438,18 @@ export class GoHarvester extends ScopeTreeHarvester {
|
|||
if (left) this.defLeftList(left, acc, op !== '=');
|
||||
return;
|
||||
}
|
||||
case 'receive_statement': {
|
||||
// `select { case v := <-ch: }` / `case v = <-ch:` — the left
|
||||
// identifier(s) are DEFS of the channel-received value; `<-ch` (right)
|
||||
// is a use of the channel. A bare `case <-ch:` has no left (uses only).
|
||||
const left = node.childForFieldName('left');
|
||||
const right = node.childForFieldName('right');
|
||||
const isShort = node.children.some((c) => !c.isNamed && c.text === ':=');
|
||||
if (isShort && left && right) this.registerListResultDefs(left, right);
|
||||
if (right) this.walkValue(right, acc);
|
||||
if (left) this.defLeftList(left, acc, false);
|
||||
return;
|
||||
}
|
||||
case 'inc_statement':
|
||||
case 'dec_statement': {
|
||||
// `x++` / `x--` — def AND use the lvalue when it's a plain identifier.
|
||||
|
|
|
|||
|
|
@ -407,6 +407,16 @@ describe('Go CfgVisitor — def/use harvest', () => {
|
|||
expect(hasUse(cfg, bindingIdx(cfg, 'k'))).toBe(true);
|
||||
void hasMayDef; // may-def path covered structurally by the conditional walk
|
||||
});
|
||||
|
||||
it('select receive `case v := <-ch` defines v, not a use-only (#2195 P2)', () => {
|
||||
const cfg = go.cfgOf(pkg(`func f(ch chan int) { select { case v := <-ch: use(v) } }`));
|
||||
const v = bindingIdx(cfg, 'v');
|
||||
// the channel-received binding is a DEF (the channel-sourced value flows
|
||||
// into v) — the bug recorded it as a use of an uninitialized var instead.
|
||||
expect(hasDef(cfg, v)).toBe(true);
|
||||
// and the channel `ch` is read.
|
||||
expect(hasUse(cfg, bindingIdx(cfg, 'ch'))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Go CfgVisitor — functionStartColumn', () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue