diff options
Diffstat (limited to 'libgo/go/fmt/print.go')
-rw-r--r-- | libgo/go/fmt/print.go | 40 |
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) } |