mirror of
https://github.com/lukaszraczylo/filepuff-mcp.git
synced 2026-10-12 04:54:27 +00:00
fix(parser): guard FindNodeAtPosition against position underflow
line/col are 1-indexed and converted via uint32(line-1); a caller passing 0 wrapped to 4294967295, feeding a garbage Point into tree-sitter. Reachable from the LSP-down AST fallback with caller-supplied coordinates. Reject non-positive positions up front. Adds tests (the function was previously 0% covered).
This commit is contained in:
@@ -16,6 +16,14 @@ func FindNodeAtPosition(tree *sitter.Tree, line, col int) *sitter.Node {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Positions are 1-indexed; reject non-positive values so the uint32
|
||||||
|
// conversion below can't underflow to a huge Row/Column (line/col == 0
|
||||||
|
// would wrap to 4294967295). Reachable from the LSP-down AST fallback with
|
||||||
|
// caller-supplied coordinates.
|
||||||
|
if line < 1 || col < 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Convert to 0-indexed
|
// Convert to 0-indexed
|
||||||
point := sitter.Point{
|
point := sitter.Point{
|
||||||
Row: uint32(line - 1), // #nosec G115 - line numbers are bounded by file size
|
Row: uint32(line - 1), // #nosec G115 - line numbers are bounded by file size
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFindNodeAtPosition(t *testing.T) {
|
||||||
|
r := NewRegistry()
|
||||||
|
content := []byte("package main\n\nfunc Hello() string { return \"hi\" }\n")
|
||||||
|
res, err := r.Parse(context.Background(), "test.go", content)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("nil tree", func(t *testing.T) {
|
||||||
|
if FindNodeAtPosition(nil, 3, 6) != nil {
|
||||||
|
t.Error("nil tree must return nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Guard against the uint32 underflow: non-positive coordinates must return
|
||||||
|
// nil, never wrap to a huge Row/Column.
|
||||||
|
t.Run("non-positive coordinates", func(t *testing.T) {
|
||||||
|
for _, c := range []struct{ line, col int }{{0, 0}, {0, 5}, {3, 0}, {-1, 4}} {
|
||||||
|
if got := FindNodeAtPosition(res.Tree, c.line, c.col); got != nil {
|
||||||
|
t.Errorf("FindNodeAtPosition(tree, %d, %d) = %v, want nil", c.line, c.col, got.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("out of range line returns nil", func(t *testing.T) {
|
||||||
|
if got := FindNodeAtPosition(res.Tree, 99999, 1); got != nil {
|
||||||
|
t.Errorf("far-out-of-range line should return nil, got %v", got.Type())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("valid position returns a node", func(t *testing.T) {
|
||||||
|
// Line 3, column 6 lands inside "Hello".
|
||||||
|
got := FindNodeAtPosition(res.Tree, 3, 6)
|
||||||
|
if got == nil {
|
||||||
|
t.Fatal("expected a node at a valid in-range position, got nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user