internal/span: switch to an offset function that doesn't panic
go/token.File.Offset panics on invalid positions, which is causing
crashes on invalid ASTs.
Change-Id: I6c698760ae92f3076a056c3560bea2e8eeb528db
Reviewed-on: https://go-review.googlesource.com/c/tools/+/169443
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/span/token.go b/internal/span/token.go
index fb4d16d..0fc0169 100644
--- a/internal/span/token.go
+++ b/internal/span/token.go
@@ -65,12 +65,16 @@
return Span{}, fmt.Errorf("file not found in FileSet")
}
s := Span{v: span{URI: FileURI(f.Name())}}
- if !r.Start.IsValid() {
- return Span{}, fmt.Errorf("invalid position for start of range")
+ var err error
+ s.v.Start.Offset, err = offset(f, r.Start)
+ if err != nil {
+ return Span{}, err
}
- s.v.Start.Offset = f.Offset(r.Start)
if r.End.IsValid() {
- s.v.End.Offset = f.Offset(r.End)
+ s.v.End.Offset, err = offset(f, r.End)
+ if err != nil {
+ return Span{}, err
+ }
}
s.v.Start.clean()
s.v.End.clean()
@@ -79,6 +83,15 @@
return s.WithPosition(converter)
}
+// offset is a copy of the Offset function in go/token, but with the adjustment
+// that it does not panic on invalid positions.
+func offset(f *token.File, pos token.Pos) (int, error) {
+ if int(pos) < f.Base() || int(pos) > f.Base()+f.Size() {
+ return 0, fmt.Errorf("invalid pos")
+ }
+ return int(pos) - f.Base(), nil
+}
+
// Range converts a Span to a Range that represents the Span for the supplied
// File.
func (s Span) Range(converter *TokenConverter) (Range, error) {
@@ -121,5 +134,5 @@
// we assume that column is in bytes here, and that the first byte of a
// line is at column 1
pos += token.Pos(col - 1)
- return l.file.Offset(pos), nil
+ return offset(l.file, pos)
}