Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/tools/cmd/gopls: panic in ToUTF16Column for certain inputs #31341

Closed
myitcv opened this issue Apr 8, 2019 · 3 comments
Closed

x/tools/cmd/gopls: panic in ToUTF16Column for certain inputs #31341

myitcv opened this issue Apr 8, 2019 · 3 comments

Comments

@myitcv
Copy link
Member

@myitcv myitcv commented Apr 8, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.2 linux/amd64
$ go list -m golang.org/x/tools
golang.org/x/tools v0.0.0-20190406165526-0d5674b3111a

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN="/home/myitcv/gostuff/src/github.com/myitcv/govim/cmd/govim/.bin"
GOCACHE="/home/myitcv/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/myitcv/gostuff"
GOPROXY=""
GORACE=""
GOROOT="/home/myitcv/gos"
GOTMPDIR=""
GOTOOLDIR="/home/myitcv/gos/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/myitcv/gostuff/src/github.com/myitcv/govim/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build292790346=/tmp/go-build -gno-record-gcc-switches"

What did you do?

The following sequence of calls/events:

Sequence of calls/events
gopls.Initialize() call; params:
&protocol.InitializeParams{
    InnerInitializeParams: protocol.InnerInitializeParams{
        ProcessID:             0,
        RootPath:              "",
        RootURI:               "file:///home/myitcv/gostuff/src/github.com/myitcv/playground",
        Capabilities:          {},
        InitializationOptions: nil,
        Trace:                 "",
    },
    WorkspaceFoldersInitializeParams: protocol.WorkspaceFoldersInitializeParams{},
}
gopls.Initialize() return; err: ; res:
&protocol.InitializeResult{
    Capabilities: protocol.ServerCapabilities{
        InnerServerCapabilities: protocol.InnerServerCapabilities{
            TextDocumentSync: map[string]interface {}{
                "change":    float64(1),
                "openClose": bool(true),
            },
            HoverProvider:      true,
            CompletionProvider: &protocol.CompletionOptions{
                TriggerCharacters:   {"."},
                AllCommitCharacters: nil,
                ResolveProvider:     false,
            },
            SignatureHelpProvider: &protocol.SignatureHelpOptions{
                TriggerCharacters: {"(", ","},
            },
            DefinitionProvider:               true,
            ReferencesProvider:               false,
            DocumentHighlightProvider:        true,
            DocumentSymbolProvider:           true,
            WorkspaceSymbolProvider:          false,
            CodeActionProvider:               true,
            CodeLensProvider:                 (*protocol.CodeLensOptions)(nil),
            DocumentFormattingProvider:       true,
            DocumentRangeFormattingProvider:  true,
            DocumentOnTypeFormattingProvider: (*struct { FirstTriggerCharacter string "json:\"firstTriggerCharacter\""; MoreTriggerCharacter []string "json:\"moreTriggerCharacter,omitempty\"" })(nil),
            RenameProvider:                   false,
            DocumentLinkProvider:             (*protocol.DocumentLinkOptions)(nil),
            ExecuteCommandProvider:           (*protocol.ExecuteCommandOptions)(nil),
            Experimental:                     nil,
        },
        ImplementationServerCapabilities:   protocol.ImplementationServerCapabilities{},
        TypeDefinitionServerCapabilities:   protocol.TypeDefinitionServerCapabilities{TypeDefinitionProvider:true},
        WorkspaceFoldersServerCapabilities: protocol.WorkspaceFoldersServerCapabilities{},
        ColorServerCapabilities:            protocol.ColorServerCapabilities{},
        FoldingRangeServerCapabilities:     protocol.FoldingRangeServerCapabilities{},
        DeclarationServerCapabilities:      protocol.DeclarationServerCapabilities{},
        SelectionRangeServerCapabilities:   protocol.SelectionRangeServerCapabilities{},
    },
    Custom: {},
}
gopls.DidOpen() call; params:
&protocol.DidOpenTextDocumentParams{
    TextDocument: protocol.TextDocumentItem{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go", LanguageID:"", Version:0, Text:"package main"},
}
gopls.DidOpen() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                1,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                2,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\n",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                3,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\ni",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                4,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nim",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                5,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimp",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                6,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimpo",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                7,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimpor",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                8,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                9,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport ",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                10,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"\"",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                11,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"f\"",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                12,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fm\"",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                13,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                14,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                15,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n\n",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                16,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n\nf",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                17,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n\nfu",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                18,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n\nfun",
        },
    },
}
gopls.DidChange() return; err: 
gopls.DidChange() call; params:
&protocol.DidChangeTextDocumentParams{
    TextDocument: protocol.VersionedTextDocumentIdentifier{
        TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
        Version:                19,
    },
    ContentChanges: {
        {
            Range:       (*protocol.Range)(nil),
            RangeLength: 0,
            Text:        "package main\n\nimport \"fmt\"\n\nfunc",
        },
    },
}
gopls.DidChange() return; err: 

followed by sending another DidChange notification with an additional " " character at the end of that input triggers:

panic: runtime error: slice bounds out of range

goroutine 230 [running]:
golang.org/x/tools/internal/span.ToUTF16Column(0x5, 0x5, 0x20, 0xc0003736a0, 0x20, 0x20, 0xffffffffffffffff, 0x5, 0x5)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/span/utf16.go:41 +0x57a
golang.org/x/tools/internal/lsp/protocol.(*ColumnMapper).Position(0xc0003c3bf0, 0x5, 0x5, 0x20, 0x0, 0x0, 0x72c87d, 0x7b38a0)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/protocol/span.go:62 +0x63
golang.org/x/tools/internal/lsp/protocol.(*ColumnMapper).Range(0xc0003c3bf0, 0xc0003c8820, 0x44, 0x5, 0x5, 0x20, 0x5, 0x5, 0x20, 0x0, ...)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/protocol/span.go:50 +0x40d
golang.org/x/tools/internal/lsp.toProtocolDiagnostics(0x8c7dc0, 0xc000353680, 0x8c7f40, 0xc0001a8000, 0xc000164a80, 0x1, 0x1, 0xc0003cc2c8, 0xc0003c3b60, 0xb67c30, ...)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/diagnostics.go:88 +0x24c
golang.org/x/tools/internal/lsp.(*Server).publishDiagnostics(0xc0001643f0, 0x8c7dc0, 0xc000353680, 0xc0001a8000, 0xc0003c87d0, 0x44, 0xc000164a80, 0x1, 0x1, 0x0, ...)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/diagnostics.go:59 +0x82
golang.org/x/tools/internal/lsp.(*Server).cacheAndDiagnose.func1(0xc0001a8000, 0xc0003c85a0, 0x44, 0xc0001643f0)
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/diagnostics.go:36 +0x21a
created by golang.org/x/tools/internal/lsp.(*Server).cacheAndDiagnose
	/home/myitcv/gostuff/pkg/mod/golang.org/x/tools@v0.0.0-20190406165526-0d5674b3111a/internal/lsp/diagnostics.go:22 +0x157

What did you expect to see?

No panic.

What did you see instead?

The above panic.

cc @stamblerre @ianthehat

@gopherbot
Copy link

@gopherbot gopherbot commented Apr 18, 2019

Change https://golang.org/cl/172667 mentions this issue: internal/lsp: add an additional check to ToUTF16Column

gopherbot pushed a commit to golang/tools that referenced this issue Apr 19, 2019
This change will at least stop the panic from occurring.

Updates golang/go#31341

Change-Id: I6b06941cfb6c020d2b37813573cb0dc068d54e65
Reviewed-on: https://go-review.googlesource.com/c/tools/+/172667
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
@gopherbot
Copy link

@gopherbot gopherbot commented Apr 25, 2019

Change https://golang.org/cl/173978 mentions this issue: internal/lsp: extensive utf16 tests

@gopherbot
Copy link

@gopherbot gopherbot commented Apr 25, 2019

Change https://golang.org/cl/173960 mentions this issue: internal/lsp: fix utf16 conversion for end of file cursor

gopherbot pushed a commit to golang/tools that referenced this issue Apr 25, 2019
Based on the work Paul Jolly did in https://go-review.googlesource.com/c/tools/+/173797
but not as internal tests and with a mildly obsessive attention to coverage.
Also has a failing test for golang/go#31341 that you can enable with -b31341

Change-Id: I528eee5304cd7191eafd3bcddb2f636c8722846f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/173978
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
@golang golang locked and limited conversation to collaborators Apr 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.