Skip to content

fix(extract): YAML walkers grow their stacks instead of capping content - #2760

Merged
DeusData merged 4 commits into
DeusData:mainfrom
gaurav0107:fix/2388-extraction-remaining-fixed-size-tsnode-w
Oct 28, 2026
Merged

DeusData merged 4 commits into
DeusData:mainfrom
gaurav0107:fix/2388-extraction-remaining-fixed-size-tsnode-w

Conversation

@gaurav0107

@gaurav0107 gaurav0107 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Part of #2388. It fixes the extract_unified.c site in the issue's list, scan_yaml_for_infra_bindings (a 512-node stack), and the walker next to it that has the same defect but isn't in the list: walk_yaml_mapping, the dotted key-path walk (a 256-frame stack). The LSP sites, extract_imports.c and the Nix helper are left for separate PRs, so the issue stays open.

walk_yaml_mapping pushes one frame for each nested mapping value. Once 256 frames were pending it stopped pushing. In a mapping with more than 256 keys whose values are mappings, every entry past the cap lost its full key_path. Only the shorter path survived, the one the walk of the nested block emits by itself (url instead of k299.url).

The infra Route pass decides on those paths. infra_payload_key denies a URL under data:, stringData: or binaryData: by its full path (#521), and with deny-wins-by-value one denied ref is enough to keep the value from being minted. With 300 entries under data:, entries 256 to 299 had no data.… ref left, so nothing denied them, and their webhook_url values were minted as infra Route nodes.

Both walkers now use cbm_walk_stack_reserve / cbm_walk_stack_release from #2375. Each starts on an on-stack chunk the same size as the old cap, so ordinary files never allocate. Wider trees spill to the memory core (class EXTRACT). If the stack cannot grow, the failure is logged as extract.walk_stack_alloc_failed and the walk stops, instead of truncating silently. Traversal order is unchanged.

Evidence

Machine: Amazon Linux 2023, x86_64, clang 15.0.7. gcc here has no libasan, so the sanitizer build uses clang.

Test main this branch
extraction: yaml_key_paths_wide_mapping_exceed_old_stack_cap (300 keys, each kN: {url: …}; every kN.url ref must exist) FAIL PASS
lang_contract: contract_edge_no_infra_routes_from_wide_payload_block_issue2388 (300 entries under data:; no infra Route) FAIL: minted 44 infra routes (expected 0) PASS
extraction: yaml_infra_bindings_wide_sequence_exceed_old_stack_cap (600-item sequence of {topic, push_endpoint}) PASS PASS

The third test does not fail on main, and I don't want to imply it does. The unified cursor walk calls scan_infra_bindings on every block_mapping, and that re-scans each mapping the capped document-level walk dropped. So the 512 cap never cost a binding under the default walk budget. The test pins the invariant now that the cap is gone.

For the RED run I put main's extract_unified.c back under the new tests:

scripts/test.sh --suites extraction CC=clang CXX=clang++ SANITIZE="-fsanitize=address -fno-omit-frame-pointer"
  main:  483 passed, 1 failed (yaml_key_paths_wide_mapping_exceed_old_stack_cap)
  fix:   484 passed
scripts/test.sh --suites lang_contract (same flags)
  main:  43 passed, 1 failed ([2388] ... minted 44 infra routes)
  fix:   44 passed
scripts/test.sh (default venue run, same flags) on the fix commit before the lang_contract test was added:
  9907 passed, 0 failed, 9 skipped (191 suites); all contract steps passed

End to end with product builds (make -f Makefile.cbm cbm) of main @ ff28841 and this branch, on a one-file repo (service.yaml), counting MATCH (r:Route) RETURN count(r):

service.yaml main this branch
data: with 300 svcN: {webhook_url: https://hN.example.com/hook} 44 (h256 … h299) 0
the same 300 entries under hooks: (control: real endpoints) 300 300

Not verified locally

  • scripts/lint.sh: cppcheck and clang-format-20 aren't installed here. git diff -U0 upstream/main..HEAD | clang-format-diff -p1 (clang-format 15) is empty locally, and the lint CI job (cppcheck + clang-format-20) passed on this PR.

Checklist

  • Every commit is signed off (git commit -s): scripts/check-dco.sh upstream/main..HEAD OK
  • Tests pass locally (make -f Makefile.cbm test): default scripts/test.sh venue run green (see above)
  • Lint passes (make -f Makefile.cbm lint-ci): not run locally; the lint CI job passed (see above)
  • New behavior is covered by a test (reproduce-first for bug fixes)

🤖 Opened with Superhuman, an open-source contribution agent.

walk_yaml_mapping (dotted key paths, 256 frames) and
scan_yaml_for_infra_bindings (512 nodes) kept their pending nodes in
fixed-size stacks and stopped pushing once full. A mapping with more than
256 nested sibling mappings lost the full key_path of every leaf past the
cap: `k299.url` was only recorded as the shorter path that the walk of a
nested block emits on its own.

The infra Route pass decides on those paths. A `data:` payload block with
300 entries lost `data.svcN.webhook_url` for N >= 256, the payload deny
never saw those values, and 44 of them were minted as infra Route nodes.

Both walkers now start on the same-sized on-stack chunk and grow through
cbm_walk_stack_reserve / cbm_walk_stack_release (DeusData#2375). If the stack
cannot grow, the failure is logged as extract.walk_stack_alloc_failed and
the walk stops, instead of truncating silently.

Part of DeusData#2388.

Signed-off-by: Gaurav Dubey <[email protected]>
@gaurav0107
gaurav0107 marked this pull request as ready for review October 22, 2026 01:46
@gaurav0107
gaurav0107 requested a review from DeusData as a code owner October 22, 2026 01:46
@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@DeusData

Copy link
Copy Markdown
Owner

Thank you very much for this, Gaurav - a careful and honest piece of work. You found a second walker with the same defect that the #2388 list had missed (walk_yaml_mapping), traced it to its real consequence (payload values under data: being minted as infra Routes once the key-path walk dropped frames), and fixed both walkers with the existing cbm_walk_stack_reserve helper from #2375. Main had moved since your CI run (another change touched the same test file), so we merged current main into your branch (one signed-off merge commit, 50ed9c3; your commit is untouched) and CI is re-running. If you push to this branch again, please pull first. We will merge once the fresh checks are green.

@gaurav0107

Copy link
Copy Markdown
Contributor Author

Thanks for the review and for merging main into the branch. Noted on 50ed9c3: I'll pull before any further push. Happy to adjust anything if the fresh checks turn something up.

@DeusData DeusData added bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges labels Oct 25, 2026
@DeusData

Copy link
Copy Markdown
Owner

Thanks again, @gaurav0107. Several other pull requests landed on main this evening, including changes in files this one also touches, so we merged current main into your branch once more (one signed-off merge commit, abdd281; your changes are untouched). That keeps the required checks honest against today's tree; we will merge once they are green. Please pull before pushing again.

@DeusData

Copy link
Copy Markdown
Owner

Thank you for your patience, @gaurav0107. CI went green on this branch, but tonight's merges on main touched tests/test_extraction.c, which this pull request also changes, so that green no longer covered today's main. We merged current main into the branch once more (one merge commit, 8012a75; your changes are untouched) and will merge once the fresh checks are green. Please pull before pushing again.

@DeusData
DeusData merged commit e425666 into DeusData:main Oct 28, 2026
26 checks passed
@DeusData

Copy link
Copy Markdown
Owner

Merged as e425666 - thank you, @gaurav0107! The YAML walkers now grow their stacks instead of stopping at a fixed size, so deeply nested YAML keeps all of its content in the graph. Thank you for picking up another piece of #2388 and for your patience.

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

Labels

bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants