Fix parser crash from tree-sitter 0.26.0's unstable Point coordinates - #9
Merged
Merged
Conversation
tree-sitter 0.26.0 has an upstream bug (already fixed, not yet released) where reading a node's Point via the named .row/.column attributes is unstable for source coordinates beyond the small-integer range. On real files (e.g. axios's index.d.ts, first triggered near line 386) this can segfault the interpreter. Tuple/index access (point[0], point[1]) is stable on both affected and unaffected tree-sitter versions. Replace the three .row accesses in graphora/parser.py with a small _point_row() helper that reads Point.row via index access. No public API, confidence tagging, or supported-language changes. Also exclude tree-sitter==0.26.0 in pyproject.toml as defense-in-depth so other/future code paths can't silently receive the broken release, while keeping >=0.23 and any future corrected release (>0.26.0) installable. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- tests/fixtures/large_coordinates.ts: a small, locally-authored TypeScript fixture with two functions past line 256 (rows 261 and 265), so relevant coordinates fall outside tree-sitter 0.26.0's affected small-integer range. - test_core_parser_large_coordinates.py: parses the fixture in an isolated subprocess (a dependency regression - including a segfault, as reproduced against unpatched code under tree-sitter 0.26.0 - becomes an ordinary, isolated test failure) and asserts the extracted function and call line numbers. - test_core_packaging.py: asserts the installed package metadata and pyproject.toml both exclude tree-sitter==0.26.0 while keeping >=0.23 and any future corrected release installable. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Bump the active version surfaces from 0.2.0 to 0.2.1 for the tree-sitter Point-coordinate compatibility fix in this PR: - pyproject.toml: [project].version - graphora/__init__.py: __version__ (also surfaced by `graphora --version`) The v0.2.0 git tag and no other historical references were changed -- this only touches active release metadata. Extend tests/core/test_core_packaging.py with test_active_version_surfaces_agree(), which asserts __version__, the pyproject.toml version, and the installed package metadata version all match, so a partial version bump fails a normal test instead of shipping inconsistently. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
README.md's banner used a repo-relative <img src="assets/banner.gif">. GitHub resolves that against the repo, but PyPI renders the packaged long description with no repository base, so the image never loads on the PyPI project page. Switch to the absolute raw-asset URL: https://raw.githubusercontent.com/Naseem77/Graphora/main/assets/banner.gif Verified the URL responds 200 with content-type: image/gif, and that it is the only source of this image in the packaged wheel/sdist long description (built graphora_kg-0.2.1 wheel + sdist, inspected dist-info/METADATA and PKG-INFO: absolute URL present, repo-relative path absent; twine check passes on both). Added test_readme_banner_uses_absolute_url_in_packaged_long_description to tests/core/test_core_packaging.py to keep this from regressing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
graphora-kg==0.2.0permitstree-sitter>=0.23, which allows the currently-latesttree-sitter==0.26.0. That release has a known upstream bug (already fixed upstream, but no corrected release is published yet): reading a node'sPointvia the named.row/.columnattributes is unstable for source coordinates beyond the small-integer range. On real files this doesn't just return a wrong number — it can segfault the interpreter.Graphora read
node.start_point.row/node.end_point.rowdirectly ingraphora/parser.py, so any large enough source file (row > 256) hit this under 0.26.0. Axios'sindex.d.tsat6ac574e0(543 lines) is a deterministic real-world trigger, first hit near line 386.This reproduces with a clean
pip install graphora-kg, a cleanmaincheckout, and the prior editable install alike — it's a real dependency-compatibility defect inmain, not local contamination.Fix
graphora/parser.py: added a_point_row()helper that reads aPoint's row via index access (point[0]) instead of the named.rowattribute. Tuple/index access is stable on both affected and unaffected tree-sitter versions. Replaced all 3 call sites (function ranges, call-site lines, symbol lines). No public API, confidence tagging, supported-language, or output changes.pyproject.toml: excludedtree-sitter==0.26.0(tree-sitter>=0.23,!=0.26.0) as defense-in-depth, so any other/future code path can't silently receive the broken release. The lower bound (>=0.23) and any future corrected release above 0.26.0 remain installable — no upper cap.Regression coverage
tests/fixtures/large_coordinates.ts: small, locally-authored TypeScript fixture with two functions past line 256 (rows 261/265, 0-based), so the relevant coordinates fall outside the affected small-integer range.tests/core/test_core_parser_large_coordinates.py: parses the fixture in an isolated subprocess, so a future dependency regression (including a segfault, as reproduced below) becomes an ordinary, isolated test failure rather than crashing the whole test run.tests/core/test_core_packaging.py: asserts both the installed package metadata andpyproject.tomlexcludetree-sitter==0.26.0while keeping>=0.23and any future corrected release installable.Validation performed
Environment: macOS arm64, Python 3.11.6,
uvfor env/dependency management.pytest -q→67 passed, 46 skipped(skips are FalkorDB-integration tests, no local server). Ran with both the resolvedtree-sitter==0.25.2and withtree-sitter==0.26.0force-installed — both pass with the fix.tree-sitter==0.26.0installed, the new regression test segfaults the subprocess (returncode == -11). Restoring the fix makes it pass. This confirms the defect is real and confirms the regression test catches it.python -m build→ clean wheel + sdist,twine check dist/*→PASSEDfor both.uv venvwith resolved dependencies (tree-sitter==0.25.2chosen automatically due to the new exclusion). Verified module provenance (graphora.parser.__file__resolves to the installed site-packages, not the source checkout) andimportlib.metadata.requires("graphora-kg")reportstree-sitter!=0.26.0,>=0.23. Re-ran the large-coordinate parse 5 times from this install — consistent, correct line numbers every time.65e8d1e2, head6ac574e0, temporary clone only — no third-party source committed):{"files": 139, "symbols": 185, "calls": 201, "imports": 279}.index.d.ts(543 lines) parsed viatree-sitter, 4 symbols extracted, max symbol line 469 (> 256, exercising the real-world trigger coordinate).tree-sitter==0.26.0force-installed — identical stats, confirming the fix holds against the actual buggy dependency on the real trigger file, not just the synthetic fixture.index.d.tscontent is identical between the base and head commits; the base/head diff itself only toucheslib/,test/, and config files, unrelated to this fix.Limitations / scope
tree-sitterrelease — none is published yet upstream. The!=0.26.0exclusion plus the safe-indexing fix is the mitigation until one ships..github/workflows/ci.ymlonly runspytestandpython -m build+twine check); those are the checks that were run here.Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com