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>
This commit is contained in:
Rebecca Stambler 2019-03-26 21:02:11 -04:00
parent 41a94eb788
commit 79af862e67
1 changed files with 18 additions and 5 deletions

View File

@ -65,12 +65,16 @@ func (r Range) Span() (Span, error) {
return Span{}, fmt.Errorf("file not found in FileSet") return Span{}, fmt.Errorf("file not found in FileSet")
} }
s := Span{v: span{URI: FileURI(f.Name())}} s := Span{v: span{URI: FileURI(f.Name())}}
if !r.Start.IsValid() { var err error
return Span{}, fmt.Errorf("invalid position for start of range") 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() { 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.Start.clean()
s.v.End.clean() s.v.End.clean()
@ -79,6 +83,15 @@ func (r Range) Span() (Span, error) {
return s.WithPosition(converter) 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 // Range converts a Span to a Range that represents the Span for the supplied
// File. // File.
func (s Span) Range(converter *TokenConverter) (Range, error) { func (s Span) Range(converter *TokenConverter) (Range, error) {
@ -121,5 +134,5 @@ func (l *TokenConverter) ToOffset(line, col int) (int, error) {
// we assume that column is in bytes here, and that the first byte of a // we assume that column is in bytes here, and that the first byte of a
// line is at column 1 // line is at column 1
pos += token.Pos(col - 1) pos += token.Pos(col - 1)
return l.file.Offset(pos), nil return offset(l.file, pos)
} }