From f8cfadacc87adf3dd49cc1c165eb4f70931fc6fe Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Mon, 2 Aug 2021 13:25:24 -0400 Subject: [PATCH] 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 Run-TryBot: Rebecca Stambler gopls-CI: kokoro TryBot-Result: Go Bot Reviewed-by: Peter Weinberger --- internal/lsp/cache/parse.go | 10 ++-------- internal/lsp/semantic.go | 10 +++++++--- internal/lsp/source/util.go | 6 ++++++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/internal/lsp/cache/parse.go b/internal/lsp/cache/parse.go index d455a252b8..e2c72442f8 100644 --- a/internal/lsp/cache/parse.go +++ b/internal/lsp/cache/parse.go @@ -1072,10 +1072,10 @@ func fixArrayType(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte // 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 @@ func fixArrayType(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte 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 073336b669..cfc8719741 100644 --- a/internal/lsp/semantic.go +++ b/internal/lsp/semantic.go @@ -236,9 +236,13 @@ func (e *encoded) strStack() string { } 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 a30cc75e8e..4ff5d5740e 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -544,3 +544,9 @@ func IsValidImport(pkgPath, importPkgPath string) bool { 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 +}