internal/lsp: handle invalid positions in semantic token debug logic
Check that a position is in range before using it.
Fixes golang/vscode-go#1656
Change-Id: I1598ebab76a1775afd8f63b9849049b31fb74a8b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/339169
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Peter Weinberger <pjw@google.com>
diff --git a/internal/lsp/cache/parse.go b/internal/lsp/cache/parse.go
index d455a25..e2c7244 100644
--- a/internal/lsp/cache/parse.go
+++ b/internal/lsp/cache/parse.go
@@ -1072,10 +1072,10 @@
// Avoid doing tok.Offset(to) since that panics if badExpr ends at EOF.
// It also panics if the position is not in the range of the file, and
// badExprs may not necessarily have good positions, so check first.
- if !inRange(tok, from) {
+ if !source.InRange(tok, from) {
return false
}
- if !inRange(tok, to-1) {
+ if !source.InRange(tok, to-1) {
return false
}
fromOffset := tok.Offset(from)
@@ -1112,12 +1112,6 @@
return replaceNode(parent, bad, at)
}
-// inRange reports whether the given position is in the given token.File.
-func inRange(tok *token.File, pos token.Pos) bool {
- size := tok.Pos(tok.Size())
- return int(pos) >= tok.Base() && pos <= size
-}
-
// precedingToken scans src to find the token preceding pos.
func precedingToken(pos token.Pos, tok *token.File, src []byte) token.Token {
s := &scanner.Scanner{}
diff --git a/internal/lsp/semantic.go b/internal/lsp/semantic.go
index 073336b..cfc8719 100644
--- a/internal/lsp/semantic.go
+++ b/internal/lsp/semantic.go
@@ -236,9 +236,13 @@
}
if len(e.stack) > 0 {
loc := e.stack[len(e.stack)-1].Pos()
- add := e.pgf.Tok.PositionFor(loc, false)
- nm := filepath.Base(add.Filename)
- msg = append(msg, fmt.Sprintf("(%s:%d,col:%d)", nm, add.Line, add.Column))
+ if !source.InRange(e.pgf.Tok, loc) {
+ msg = append(msg, fmt.Sprintf("invalid position %v for %s", loc, e.pgf.URI))
+ } else {
+ add := e.pgf.Tok.PositionFor(loc, false)
+ nm := filepath.Base(add.Filename)
+ msg = append(msg, fmt.Sprintf("(%s:%d,col:%d)", nm, add.Line, add.Column))
+ }
}
msg = append(msg, "]")
return strings.Join(msg, " ")
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index a30cc75..4ff5d57 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -544,3 +544,9 @@
func IsCommandLineArguments(s string) bool {
return strings.Contains(s, "command-line-arguments")
}
+
+// InRange reports whether the given position is in the given token.File.
+func InRange(tok *token.File, pos token.Pos) bool {
+ size := tok.Pos(tok.Size())
+ return int(pos) >= tok.Base() && pos <= size
+}