Skip to content

test(point): regression test for Point row/column reference counting (#466) - #473

Closed
blarghmatey wants to merge 1 commit into
tree-sitter:masterfrom
mitodl:fix/point-refcount-regression-test
Closed

test(point): regression test for Point row/column reference counting (#466)#473
blarghmatey wants to merge 1 commit into
tree-sitter:masterfrom
mitodl:fix/point-refcount-regression-test

Conversation

@blarghmatey

Copy link
Copy Markdown

Summary

Adds a regression test for the Point.row / Point.column reference-counting bug fixed in #466. That PR corrected the getters but did not add a test, and the existing suite can't catch this class of bug (its start_point assertions all use small, immortal-int values).

Background

Before #466, point_get_row / point_get_column returned PyTuple_GetItem(self, i) — a borrowed reference — where a get/set getter must return a new reference. The row/column int was left one refcount too low, so it was freed prematurely and corrupted the pymalloc free list, eventually causing a hard SIGSEGV.

It only reproduces for non-immortal ints — i.e. line/column numbers past CPython's small-int cache (>256) — which is why it surfaced when indexing real, large source files but never with small test fixtures. I ran into it downstream and tracked it to this getter (independently confirmed with AddressSanitizer: a wild TSNode pointer in ts_node_end_byte, one over-decref removed and the crash disappears). See #472 for the original report.

The test

test_point_getters_return_new_references builds a node whose start point is (500, 500) (both values outside the immortal range) and asserts each getter increments the referent's refcount by exactly one. It measures refcounts via tuple subscripting (point[i], which is correctly owned) and asserts before the borrowed reference can do harm, so it fails cleanly on the pre-#466 binding rather than crashing.

Verified:

The test is skipped on non-CPython implementations (no sys.getrefcount).

…sion

tree-sitter#466 fixed the `Point.row` / `Point.column` getters to return a new
reference instead of a borrowed one, but added no test. The borrowed
reference left the underlying row/column int one refcount too low,
prematurely freeing it and corrupting the allocator free list —
surfacing later as a hard SIGSEGV when indexing real files (the crash
only reproduces for non-immortal ints, i.e. line/column numbers past the
small-int cache, so small fixtures never tripped it).

Add a regression test that asserts each getter takes its own reference,
using a node whose start point is (500, 500) so the values are outside
the immortal-int range. The test fails cleanly on the pre-tree-sitter#466 binding
and passes on the fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ObserverOfTime

Copy link
Copy Markdown
Member

Thanks but this isn't necessary.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants