From 57f56abcb06a73575f280dd88c01bd8665883fa9 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Mon, 21 Nov 2022 14:45:14 -0500 Subject: [PATCH] gopls/internal/lsp/source: avoid panic(nil) The previous code used panic(nil) as a longjump. However, if a library function such as Node.Pos() were to panic(nil), we would catch it spuriously instead of reporting the panic by crashing the program. This change uses a new type, found, as a sentinal for the non-local jump. Updates golang/go#25448 Change-Id: I2439432a7ca477d0c25c9c848a98308a378b089b Reviewed-on: https://go-review.googlesource.com/c/tools/+/452515 Reviewed-by: Russ Cox Run-TryBot: Alan Donovan TryBot-Result: Gopher Robot --- gopls/internal/lsp/source/hover.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gopls/internal/lsp/source/hover.go b/gopls/internal/lsp/source/hover.go index 26d5e23ad3..3d09e102f7 100644 --- a/gopls/internal/lsp/source/hover.go +++ b/gopls/internal/lsp/source/hover.go @@ -895,10 +895,14 @@ func anyNonEmpty(x []string) bool { // // It returns (nil, nil) if no Field or Decl is found at pos. func FindDeclAndField(files []*ast.File, pos token.Pos) (decl ast.Decl, field *ast.Field) { - // panic(nil) breaks off the traversal and + // panic(found{}) breaks off the traversal and // causes the function to return normally. + type found struct{} defer func() { - if x := recover(); x != nil { + switch x := recover().(type) { + case nil: + case found: + default: panic(x) } }() @@ -930,7 +934,7 @@ func FindDeclAndField(files []*ast.File, pos token.Pos) (decl ast.Decl, field *a break } } - panic(nil) // found + panic(found{}) } } @@ -953,7 +957,7 @@ func FindDeclAndField(files []*ast.File, pos token.Pos) (decl ast.Decl, field *a case *ast.FuncDecl: if n.Name.Pos() == pos { decl = n - panic(nil) // found + panic(found{}) } case *ast.GenDecl: @@ -962,13 +966,13 @@ func FindDeclAndField(files []*ast.File, pos token.Pos) (decl ast.Decl, field *a case *ast.TypeSpec: if spec.Name.Pos() == pos { decl = n - panic(nil) // found + panic(found{}) } case *ast.ValueSpec: for _, id := range spec.Names { if id.Pos() == pos { decl = n - panic(nil) // found + panic(found{}) } } }