internal/span: fix off-by-one in ToUTF16Column
Change-Id: I8c8344046b13f2606d7257ef8632e0426e15a85b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/173498
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/span/utf16.go b/internal/span/utf16.go
index 4439acb..887e3be 100644
--- a/internal/span/utf16.go
+++ b/internal/span/utf16.go
@@ -36,12 +36,12 @@
return -1, fmt.Errorf("ToUTF16Column: offsets %v-%v outside file contents (%v)", lineOffset, offset, len(content))
}
// Use the offset to pick out the line start.
- // This cannot panic: offset > len(content) and lineOffset < offset.
+ // This cannot panic: offset > len(content) and lineOffset < offset.
start := content[lineOffset:]
// Now, truncate down to the supplied column.
- if col >= len(start) {
- return -1, fmt.Errorf("ToUTF16Column: line (%v) is shorter than column (%v)", len(start), col)
+ if col > len(start) { // col is 1-indexed
+ return -1, fmt.Errorf("ToUTF16Column: length of line (%v) is less than column (%v)", len(start), col)
}
start = start[:col]
// and count the number of utf16 characters
diff --git a/internal/span/utf16_test.go b/internal/span/utf16_test.go
index 3a3b659..5f97108 100644
--- a/internal/span/utf16_test.go
+++ b/internal/span/utf16_test.go
@@ -27,7 +27,7 @@
c := span.NewContentConverter("test", input)
for line := 1; line <= 9; line++ {
runeColumn, runeChr := 0, 0
- for chr := 1; chr <= 9; chr++ {
+ for chr := 1; chr <= 10; chr++ {
switch {
case chr <= line:
runeChr = chr
@@ -67,3 +67,28 @@
}
}
}
+
+func TestUTF16Errors(t *testing.T) {
+ var input = []byte(`
+hello
+world
+`)[1:]
+ for _, test := range []struct {
+ line, col, offset int
+ want string
+ }{
+ {
+ 1, 6, 12,
+ "ToUTF16Column: length of line (5) is less than column (6)",
+ },
+ {
+ 1, 6, 13,
+ "ToUTF16Column: offsets 8-13 outside file contents (12)",
+ },
+ } {
+ p := span.NewPoint(test.line, test.col, test.offset)
+ if _, err := span.ToUTF16Column(p, input); err == nil || err.Error() != test.want {
+ t.Errorf("expected %v, got %v", test.want, err)
+ }
+ }
+}