summaryrefslogtreecommitdiff
path: root/libgo/go/fmt/print.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/fmt/print.go')
-rw-r--r--libgo/go/fmt/print.go40
1 files changed, 38 insertions, 2 deletions
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 59a30d221e9..8d3e97c3ab1 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -285,12 +285,22 @@ func getField(v reflect.Value, i int) reflect.Value {
return val
}
+// tooLarge reports whether the magnitude of the integer is
+// too large to be used as a formatting width or precision.
+func tooLarge(x int) bool {
+ const max int = 1e6
+ return x > max || x < -max
+}
+
// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
if start >= end {
return 0, false, end
}
for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
+ if tooLarge(num) {
+ return 0, false, end // Overflow; crazy long number most likely.
+ }
num = num*10 + int(s[newi]-'0')
isnum = true
}
@@ -789,6 +799,8 @@ func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) {
case []byte:
p.fmtBytes(f, verb, nil, depth)
wasString = verb == 's'
+ case reflect.Value:
+ return p.printReflectValue(f, verb, depth)
default:
// If the type is not simple, it might have methods.
if handled := p.handleMethods(verb, depth); handled {
@@ -845,6 +857,8 @@ func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasSt
p.value = value
BigSwitch:
switch f := value; f.Kind() {
+ case reflect.Invalid:
+ p.buf.WriteString("<invalid reflect.Value>")
case reflect.Bool:
p.fmtBool(f.Bool(), verb)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -1016,6 +1030,10 @@ func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int
if argNum < len(a) {
num, isInt = a[argNum].(int)
newArgNum = argNum + 1
+ if tooLarge(num) {
+ num = 0
+ isInt = false
+ }
}
return
}
@@ -1027,6 +1045,11 @@ func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int
// up to the closing paren, if present, and whether the number parsed
// ok. The bytes to consume will be 1 if no closing paren is present.
func parseArgNumber(format string) (index int, wid int, ok bool) {
+ // There must be at least 3 bytes: [n].
+ if len(format) < 3 {
+ return 0, 1, false
+ }
+
// Find closing bracket.
for i := 1; i < len(format); i++ {
if format[i] == ']' {
@@ -1053,7 +1076,7 @@ func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum
return index, i + wid, true
}
p.goodArgNum = false
- return argNum, i + wid, true
+ return argNum, i + wid, ok
}
func (p *pp) doPrintf(format string, a []interface{}) {
@@ -1105,9 +1128,17 @@ func (p *pp) doPrintf(format string, a []interface{}) {
if i < end && format[i] == '*' {
i++
p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
+
if !p.fmt.widPresent {
p.buf.Write(badWidthBytes)
}
+
+ // We have a negative width, so take its value and ensure
+ // that the minus flag is set
+ if p.fmt.wid < 0 {
+ p.fmt.wid = -p.fmt.wid
+ p.fmt.minus = true
+ }
afterIndex = false
} else {
p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
@@ -1123,9 +1154,14 @@ func (p *pp) doPrintf(format string, a []interface{}) {
p.goodArgNum = false
}
argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
- if format[i] == '*' {
+ if i < end && format[i] == '*' {
i++
p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
+ // Negative precision arguments don't make sense
+ if p.fmt.prec < 0 {
+ p.fmt.prec = 0
+ p.fmt.precPresent = false
+ }
if !p.fmt.precPresent {
p.buf.Write(badPrecBytes)
}