Skip to content

Commit 44b54b9

Browse files
TapirLiugopherbot
authored andcommitted
strings,bytes: improve Repeat panic messages
The Repeat("-", maxInt) call should produce panic: runtime error: makeslice: len out of range instead of panic: strings: Repeat output length overflow This PR is only for theory perfection. Change-Id: If67d87b147d666fbbb7238656f2a0cb6cf1dbb5b GitHub-Last-Rev: 29dc0cb GitHub-Pull-Request: #67068 Reviewed-on: https://go-review.googlesource.com/c/go/+/581936 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 2f5b420 commit 44b54b9

File tree

4 files changed

+64
-34
lines changed

4 files changed

+64
-34
lines changed

src/bytes/bytes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ func Repeat(b []byte, count int) []byte {
583583
if count < 0 {
584584
panic("bytes: negative Repeat count")
585585
}
586-
if len(b) >= maxInt/count {
586+
if len(b) > maxInt/count {
587587
panic("bytes: Repeat output length overflow")
588588
}
589589
n := len(b) * count

src/bytes/bytes_test.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,33 +1242,48 @@ func repeat(b []byte, count int) (err error) {
12421242

12431243
// See Issue golang.org/issue/16237
12441244
func TestRepeatCatchesOverflow(t *testing.T) {
1245-
tests := [...]struct {
1245+
type testCase struct {
12461246
s string
12471247
count int
12481248
errStr string
1249-
}{
1249+
}
1250+
1251+
runTestCases := func(prefix string, tests []testCase) {
1252+
for i, tt := range tests {
1253+
err := repeat([]byte(tt.s), tt.count)
1254+
if tt.errStr == "" {
1255+
if err != nil {
1256+
t.Errorf("#%d panicked %v", i, err)
1257+
}
1258+
continue
1259+
}
1260+
1261+
if err == nil || !strings.Contains(err.Error(), tt.errStr) {
1262+
t.Errorf("%s#%d got %q want %q", prefix, i, err, tt.errStr)
1263+
}
1264+
}
1265+
}
1266+
1267+
const maxInt = int(^uint(0) >> 1)
1268+
1269+
runTestCases("", []testCase{
12501270
0: {"--", -2147483647, "negative"},
1251-
1: {"", int(^uint(0) >> 1), ""},
1271+
1: {"", maxInt, ""},
12521272
2: {"-", 10, ""},
12531273
3: {"gopher", 0, ""},
12541274
4: {"-", -1, "negative"},
12551275
5: {"--", -102, "negative"},
12561276
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
1257-
}
1258-
1259-
for i, tt := range tests {
1260-
err := repeat([]byte(tt.s), tt.count)
1261-
if tt.errStr == "" {
1262-
if err != nil {
1263-
t.Errorf("#%d panicked %v", i, err)
1264-
}
1265-
continue
1266-
}
1277+
})
12671278

1268-
if err == nil || !strings.Contains(err.Error(), tt.errStr) {
1269-
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
1270-
}
1279+
const is64Bit = 1<<(^uintptr(0)>>63)/2 != 0
1280+
if !is64Bit {
1281+
return
12711282
}
1283+
1284+
runTestCases("64-bit", []testCase{
1285+
0: {"-", maxInt, "out of range"},
1286+
})
12721287
}
12731288

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

src/strings/strings.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ func Repeat(s string, count int) string {
570570
if count < 0 {
571571
panic("strings: negative Repeat count")
572572
}
573-
if len(s) >= maxInt/count {
573+
if len(s) > maxInt/count {
574574
panic("strings: Repeat output length overflow")
575575
}
576576
n := len(s) * count

src/strings/strings_test.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,33 +1170,48 @@ func repeat(s string, count int) (err error) {
11701170

11711171
// See Issue golang.org/issue/16237
11721172
func TestRepeatCatchesOverflow(t *testing.T) {
1173-
tests := [...]struct {
1173+
type testCase struct {
11741174
s string
11751175
count int
11761176
errStr string
1177-
}{
1177+
}
1178+
1179+
runTestCases := func(prefix string, tests []testCase) {
1180+
for i, tt := range tests {
1181+
err := repeat(tt.s, tt.count)
1182+
if tt.errStr == "" {
1183+
if err != nil {
1184+
t.Errorf("#%d panicked %v", i, err)
1185+
}
1186+
continue
1187+
}
1188+
1189+
if err == nil || !Contains(err.Error(), tt.errStr) {
1190+
t.Errorf("%s#%d got %q want %q", prefix, i, err, tt.errStr)
1191+
}
1192+
}
1193+
}
1194+
1195+
const maxInt = int(^uint(0) >> 1)
1196+
1197+
runTestCases("", []testCase{
11781198
0: {"--", -2147483647, "negative"},
1179-
1: {"", int(^uint(0) >> 1), ""},
1199+
1: {"", maxInt, ""},
11801200
2: {"-", 10, ""},
11811201
3: {"gopher", 0, ""},
11821202
4: {"-", -1, "negative"},
11831203
5: {"--", -102, "negative"},
11841204
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
1185-
}
1186-
1187-
for i, tt := range tests {
1188-
err := repeat(tt.s, tt.count)
1189-
if tt.errStr == "" {
1190-
if err != nil {
1191-
t.Errorf("#%d panicked %v", i, err)
1192-
}
1193-
continue
1194-
}
1205+
})
11951206

1196-
if err == nil || !Contains(err.Error(), tt.errStr) {
1197-
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
1198-
}
1207+
const is64Bit = 1<<(^uintptr(0)>>63)/2 != 0
1208+
if !is64Bit {
1209+
return
11991210
}
1211+
1212+
runTestCases("64-bit", []testCase{
1213+
0: {"-", maxInt, "out of range"},
1214+
})
12001215
}
12011216

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

0 commit comments

Comments
 (0)