Skip to content

Commit ac06e95

Browse files
authored
Merge pull request #76 from smacker/fix-query-cursor-segfault
Fix segfault in QueryCursor
2 parents 1191a82 + 7621c20 commit ac06e95

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

bindings.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,8 @@ func (q *Query) StringValueForId(id uint32) string {
818818
type QueryCursor struct {
819819
c *C.TSQueryCursor
820820
t *Tree
821+
// keep a pointer to the query to avoid garbage collection
822+
q *Query
821823

822824
isClosed bool
823825
}
@@ -832,6 +834,7 @@ func NewQueryCursor() *QueryCursor {
832834

833835
// Exec executes the query on a given syntax node.
834836
func (qc *QueryCursor) Exec(q *Query, n *Node) {
837+
qc.q = q
835838
qc.t = n.t
836839
C.ts_query_cursor_exec(qc.c, q.c, n.c)
837840
}

bindings_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,36 @@ func TestLeakParseInput(t *testing.T) {
596596
assert.Less(t, m.Alloc, uint64(1024*1024))
597597
}
598598

599+
// see https://github.com/smacker/go-tree-sitter/issues/75
600+
func TestCursorKeepsQuery(t *testing.T) {
601+
source := bytes.Repeat([]byte("1 + 1"), 10000)
602+
603+
parser := NewParser()
604+
parser.SetLanguage(getTestGrammar())
605+
606+
tree := parser.Parse(nil, source)
607+
root := tree.RootNode()
608+
609+
for i := 0; i < 100; i++ {
610+
query, _ := NewQuery(
611+
[]byte("(number) @match"),
612+
getTestGrammar(),
613+
)
614+
615+
qc := NewQueryCursor()
616+
617+
qc.Exec(query, root)
618+
619+
for {
620+
// ensure qc.NextMatch() doesn't cause a segfault
621+
match, exists := qc.NextMatch()
622+
if !exists || match == nil {
623+
break
624+
}
625+
}
626+
}
627+
}
628+
599629
func BenchmarkParse(b *testing.B) {
600630
ctx := context.Background()
601631
parser := NewParser()

0 commit comments

Comments
 (0)