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")
}
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 @@ func (r Range) Span() (Span, error) {
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 @@ func (l *TokenConverter) ToOffset(line, col int) (int, error) {
// 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)
}