Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

strings,bytes: improve Repeat panic messages #67068

Closed
wants to merge 16 commits into from
Closed
2 changes: 1 addition & 1 deletion src/bytes/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ func Repeat(b []byte, count int) []byte {
if count < 0 {
panic("bytes: negative Repeat count")
}
if len(b) >= maxInt/count {
if len(b) > maxInt/count {
panic("bytes: Repeat output length overflow")
}
n := len(b) * count
Expand Down
47 changes: 31 additions & 16 deletions src/bytes/bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1242,33 +1242,48 @@ func repeat(b []byte, count int) (err error) {

// See Issue golang.org/issue/16237
func TestRepeatCatchesOverflow(t *testing.T) {
tests := [...]struct {
type testCase struct {
s string
count int
errStr string
}{
}

runTestCases := func(prefix string, tests []testCase) {
for i, tt := range tests {
err := repeat([]byte(tt.s), tt.count)
if tt.errStr == "" {
if err != nil {
t.Errorf("#%d panicked %v", i, err)
}
continue
}

if err == nil || !strings.Contains(err.Error(), tt.errStr) {
t.Errorf("%s#%d got %q want %q", prefix, i, err, tt.errStr)
}
}
}

const maxInt = int(^uint(0) >> 1)

runTestCases("", []testCase{
0: {"--", -2147483647, "negative"},
1: {"", int(^uint(0) >> 1), ""},
1: {"", maxInt, ""},
2: {"-", 10, ""},
3: {"gopher", 0, ""},
4: {"-", -1, "negative"},
5: {"--", -102, "negative"},
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
}

for i, tt := range tests {
err := repeat([]byte(tt.s), tt.count)
if tt.errStr == "" {
if err != nil {
t.Errorf("#%d panicked %v", i, err)
}
continue
}
})

if err == nil || !strings.Contains(err.Error(), tt.errStr) {
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
}
const is64Bit = 1<<(^uintptr(0)>>63)/2 != 0
if !is64Bit {
return
}

runTestCases("64-bit", []testCase{
0: {"-", maxInt, "out of range"},
})
}

func runesEqual(a, b []rune) bool {
Expand Down
2 changes: 1 addition & 1 deletion src/strings/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ func Repeat(s string, count int) string {
if count < 0 {
panic("strings: negative Repeat count")
}
if len(s) >= maxInt/count {
if len(s) > maxInt/count {
panic("strings: Repeat output length overflow")
}
n := len(s) * count
Expand Down
47 changes: 31 additions & 16 deletions src/strings/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1170,33 +1170,48 @@ func repeat(s string, count int) (err error) {

// See Issue golang.org/issue/16237
func TestRepeatCatchesOverflow(t *testing.T) {
tests := [...]struct {
type testCase struct {
s string
count int
errStr string
}{
}

runTestCases := func(prefix string, tests []testCase) {
for i, tt := range tests {
err := repeat(tt.s, tt.count)
if tt.errStr == "" {
if err != nil {
t.Errorf("#%d panicked %v", i, err)
}
continue
}

if err == nil || !Contains(err.Error(), tt.errStr) {
t.Errorf("%s#%d got %q want %q", prefix, i, err, tt.errStr)
}
}
}

const maxInt = int(^uint(0) >> 1)

runTestCases("", []testCase{
0: {"--", -2147483647, "negative"},
1: {"", int(^uint(0) >> 1), ""},
1: {"", maxInt, ""},
2: {"-", 10, ""},
3: {"gopher", 0, ""},
4: {"-", -1, "negative"},
5: {"--", -102, "negative"},
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
}

for i, tt := range tests {
err := repeat(tt.s, tt.count)
if tt.errStr == "" {
if err != nil {
t.Errorf("#%d panicked %v", i, err)
}
continue
}
})

if err == nil || !Contains(err.Error(), tt.errStr) {
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
}
const is64Bit = 1<<(^uintptr(0)>>63)/2 != 0
if !is64Bit {
return
}

runTestCases("64-bit", []testCase{
0: {"-", maxInt, "out of range"},
})
}

func runesEqual(a, b []rune) bool {
Expand Down