Skip to content

fix(pipeline): USAGE and WRITES edges have no cross-language guard — 31% of WRITES on a Go+C repo cross the Go/C boundary #1928

Closed

Description

@ilyabrykau-orca

fix(pipeline): USAGE and WRITES edges have no cross-language guard

Status: fix open — PR #1937 (cbm_suppress_cross_language_ref() at all four resolver sites — sequential and parallel twins; the sequential-only first cut left 344 Go→C WRITES alive). Measured: Go→C/C++ WRITES 835 → 0, USAGE 1545 → 0, C→Go 15/90 → 0; 6432 reference edges dropped, all cross-language, none same-language; CALLS/IMPORTS byte-identical. Unblocks #1935 (with #1942 as the same-language other half).

What happens

#725 gave CALLS a cross-language guard (cbm_suppress_cross_language_suffix_match). USAGE, WRITES and READS resolve through the same short-name registry — pass_usages.c (resolve_usage_edges fallback, resolve_rw_edges) and their parallel twins in pass_parallel.c (resolve_file_usages, resolve_file_rw) — and never consult it. On a Go+C tree (any eBPF/kernel component), every identifier existing in both languages produces an edge across the boundary.

Damage measured (~1150-file Go+C repo, 15.8k nodes)

edge type total Go → C/C++ C/C++ → Go cross share
WRITES 2681 835 15 31.7%
USAGE 29198 1545 90 5.6%
CALLS 19920 76 31 0.5% (guard active)

Representative: dozens of Go test functions each declaring a local event produced WRITES edges to a local variable inside an eBPF C probe. The full dropped-edge breakdown is wider than Go↔C: Go→.json 3034 (config keys), Go→.hpp/.h 1612, Go→.sh/.yaml 443.

Minimal reproduction

// probe_test.go
package app

import "testing"

func TestEvent(t *testing.T) {
    event := 1
    _ = event
}
/* probe.c */
static int handle(void) {
    int event = 0;
    return event;
}

Index both → a WRITES edge from the Go test into the C event. Expected: none — Go cannot touch a C translation unit's identifiers.

Detection recipe

SELECT e.type, count(*) FROM edges e
JOIN nodes s ON s.id = e.source_id JOIN nodes t ON t.id = e.target_id
WHERE e.type IN ('WRITES','USAGE','CALLS') AND s.file_path LIKE '%.go'
  AND (t.file_path LIKE '%.c' OR t.file_path LIKE '%.h'
    OR t.file_path LIKE '%.cpp' OR t.file_path LIKE '%.hpp')
GROUP BY 1;  -- repeat with source/target swapped

Fix shape (as landed)

One pure predicate next to the #725 guard. Two deliberate differences from CALLS: no strategy parameter (a reference edge carries no import-closure evidence, so every registry strategy is a bare-name guess across a boundary — the unpenalized-unique_name carve-out of #1572 does not apply), and C/C++ are one family (.h maps to CBM_LANG_CPP; a .c file referencing its own header is not a boundary). LSP-backed semantic references resolve before the fallback and never reach it — that path is where a genuine cgo binding (#1929) would live. JS/TS family exemption as in #725.

Related: #725, #1935/#1940 (blocked on this), #1942 (same-language other half), #787; tracked in #1932.

Activity

  1. added 5 commits that reference this issue on Aug 30, 2026
    d6417ad
    37c0ef4
    c175ca1
    7297139
    cc00a02
  2. DeusData commented on Aug 31, 2026

    @DeusData
    Owner

    Fixed on main by d6417ada0ec5bb144c0694d076fc504b6fa14e06, merged as fcd8bfc1066db4f1649d3537579c355c4da34437 (#1937).

    The guard is cbm_suppress_cross_language_ref(caller_lang, target_file_path) in registry.c, consulted on the registry-fallback branch of resolve_usage_edges and on resolve_rw_edges. Reviewed against the recall risk specifically: it fails open on every ambiguous input — unknown caller language, missing or empty target path, unknown target language, same language, the JS/TS family, and the C/C++ family all return "keep". It suppresses only when both languages are known and differ across families, which is where the bind is impossible by construction rather than merely unlikely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    windowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions