}
}
}
+
+// Test that erroneous String routine doesn't cause fatal recursion.
+var recurCount = 0
+
+type Recur struct {
+ i int
+ failed *bool
+}
+
+func (r Recur) String() string {
+ if recurCount++; recurCount > 10 {
+ *r.failed = true
+ return "FAIL"
+ }
+ // This will call badVerb. Before the fix, that would cause us to recur into
+ // this routine to print %!p(value). Now we don't call the user's method
+ // during an error.
+ return Sprintf("recur@%p value: %d", r, r.i)
+}
+
+func TestBadVerbRecursion(t *testing.T) {
+ failed := false
+ r := Recur{3, &failed}
+ Sprintf("recur@%p value: %d\n", &r, r.i)
+ if failed {
+ t.Error("fail with pointer")
+ }
+ failed = false
+ r = Recur{4, &failed}
+ Sprintf("recur@%p, value: %d\n", r, r.i)
+ if failed {
+ t.Error("fail with value")
+ }
+}
type pp struct {
n int
panicking bool
+ erroring bool // printing an error condition
buf bytes.Buffer
// field holds the current item, as an interface{}.
field interface{}
func newPrinter() *pp {
p := ppFree.get().(*pp)
p.panicking = false
+ p.erroring = false
p.fmt.init(&p.buf)
return p
}
}
func (p *pp) badVerb(verb rune) {
+ p.erroring = true
p.add('%')
p.add('!')
p.add(verb)
p.buf.Write(nilAngleBytes)
}
p.add(')')
+ p.erroring = false
}
func (p *pp) fmtBool(v bool, verb rune) {
}
func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) {
+ if p.erroring {
+ return
+ }
// Is it a Formatter?
if formatter, ok := p.field.(Formatter); ok {
handled = true