1
0
mirror of https://github.com/golang/go synced 2024-11-12 09:20:22 -07:00

fmt: fix up zero padding

If the padding is huge, we crashed by blowing the buffer. That's easy: make sure
we have a big enough buffer by allocating in problematic cases.
Zero padding floats was just wrong in general: the space would appear in the
middle.

Fixes #6044.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/12498043
This commit is contained in:
Rob Pike 2013-08-07 08:38:46 +10:00
parent 1104a2afb1
commit f59064de80
2 changed files with 26 additions and 2 deletions

View File

@ -493,6 +493,17 @@ var fmtTests = []struct {
// Used to crash because nByte didn't allow for a sign.
{"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"},
// Used to panic.
{"%0100d", 1, "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"},
{"%0100d", -1, "-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"},
{"%0.100f", 1.0, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
{"%0.100f", -1.0, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
// Zero padding floats used to put the minus sign in the middle.
{"%020f", -1.0, "-000000000001.000000"},
{"%20f", -1.0, " -1.000000"},
{"%0100f", -1.0, "-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.000000"},
// Complex fmt used to leave the plus flag set for future entries in the array
// causing +2+0i and +3+0i instead of 2+0i and 3+0i.
{"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},

View File

@ -160,6 +160,11 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
}
var buf []byte = f.intbuf[0:]
if f.widPresent && f.wid > nByte {
// We're going to need a bigger boat.
buf = make([]byte, f.wid)
}
negative := signedness == signed && a < 0
if negative {
a = -a
@ -182,7 +187,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// a is made into unsigned ua. we could make things
// marginally faster by splitting the 32-bit case out into a separate
// block but it's not worth the duplication, so ua has 64 bits.
i := len(f.intbuf)
i := len(buf)
ua := uint64(a)
for ua >= base {
i--
@ -191,7 +196,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
}
i--
buf[i] = digits[ua]
for i > 0 && prec > nByte-i {
for i > 0 && prec > len(buf)-i {
i--
buf[i] = '0'
}
@ -354,6 +359,14 @@ func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
// The formatted number starts at slice[1].
switch slice[1] {
case '-', '+':
// If we're zero padding, want the sign before the leading zeros.
// Achieve this by writing the sign out and padding the postive number.
if f.zero && f.widPresent && f.wid > len(slice) {
f.buf.WriteByte(slice[1])
f.wid--
f.pad(slice[2:])
return
}
// We're set; drop the leading space.
slice = slice[1:]
default: