cmd/stringer: fix panic caused by integer overflow

When String() was called on the maximum value of an integer type (eg
255 for uint8) this would cause an integer overflow, which would cause
an index error later in the code.

Fixed by re-arranging the code slightly.

Fixes golang/go#10563

Change-Id: I9fd016afc5eea22adbc3843f6081091fd50deccf
Reviewed-on: https://go-review.googlesource.com/9255
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Nick Craig-Wood 2015-04-23 22:54:52 +01:00 коммит произвёл Rob Pike
Родитель 27e692e6ec
Коммит 578c521fc2
3 изменённых файлов: 36 добавлений и 5 удалений

Просмотреть файл

@ -51,7 +51,7 @@ const _Day_name = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
var _Day_index = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
func (i Day) String() string {
if i < 0 || i+1 >= Day(len(_Day_index)) {
if i < 0 || i >= Day(len(_Day_index)-1) {
return fmt.Sprintf("Day(%d)", i)
}
return _Day_name[_Day_index[i]:_Day_index[i+1]]
@ -77,7 +77,7 @@ var _Number_index = [...]uint8{0, 3, 6, 11}
func (i Number) String() string {
i -= 1
if i < 0 || i+1 >= Number(len(_Number_index)) {
if i < 0 || i >= Number(len(_Number_index)-1) {
return fmt.Sprintf("Number(%d)", i+1)
}
return _Number_name[_Number_index[i]:_Number_index[i+1]]
@ -145,7 +145,7 @@ var _Num_index = [...]uint8{0, 3, 6, 8, 10, 12}
func (i Num) String() string {
i -= -2
if i < 0 || i+1 >= Num(len(_Num_index)) {
if i < 0 || i >= Num(len(_Num_index)-1) {
return fmt.Sprintf("Num(%d)", i+-2)
}
return _Num_name[_Num_index[i]:_Num_index[i+1]]

Просмотреть файл

@ -562,7 +562,7 @@ func (g *Generator) buildOneRun(runs [][]Value, typeName string) {
// [2]: size of index element (8 for uint8 etc.)
// [3]: less than zero check (for signed types)
const stringOneRun = `func (i %[1]s) String() string {
if %[3]si+1 >= %[1]s(len(_%[1]s_index)) {
if %[3]si >= %[1]s(len(_%[1]s_index)-1) {
return fmt.Sprintf("%[1]s(%%d)", i)
}
return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]]
@ -578,7 +578,7 @@ const stringOneRun = `func (i %[1]s) String() string {
*/
const stringOneRunWithOffset = `func (i %[1]s) String() string {
i -= %[2]s
if %[4]si+1 >= %[1]s(len(_%[1]s_index)) {
if %[4]si >= %[1]s(len(_%[1]s_index)-1) {
return fmt.Sprintf("%[1]s(%%d)", i + %[2]s)
}
return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]]

31
cmd/stringer/testdata/unum2.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Unsigned integers - check maximum size
package main
import "fmt"
type Unum2 uint8
const (
Zero Unum2 = iota
One
Two
)
func main() {
ck(Zero, "Zero")
ck(One, "One")
ck(Two, "Two")
ck(3, "Unum2(3)")
ck(255, "Unum2(255)")
}
func ck(unum Unum2, str string) {
if fmt.Sprint(unum) != str {
panic("unum.go: " + str)
}
}