From 578c521fc29d6b5e17e052d4382ef72664fc1e2d Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 23 Apr 2015 22:54:52 +0100 Subject: [PATCH] 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 --- cmd/stringer/golden_test.go | 6 +++--- cmd/stringer/stringer.go | 4 ++-- cmd/stringer/testdata/unum2.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 cmd/stringer/testdata/unum2.go diff --git a/cmd/stringer/golden_test.go b/cmd/stringer/golden_test.go index 76e81c3625..12df238fa0 100644 --- a/cmd/stringer/golden_test.go +++ b/cmd/stringer/golden_test.go @@ -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]] diff --git a/cmd/stringer/stringer.go b/cmd/stringer/stringer.go index 6294100116..be87dec708 100644 --- a/cmd/stringer/stringer.go +++ b/cmd/stringer/stringer.go @@ -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]] diff --git a/cmd/stringer/testdata/unum2.go b/cmd/stringer/testdata/unum2.go new file mode 100644 index 0000000000..edbbedf33a --- /dev/null +++ b/cmd/stringer/testdata/unum2.go @@ -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) + } +}