Skip to content

Commit d669b04

Browse files
authored
Swallow panic when calling String or Error (#221)
If a panic occurs while calling String or Error, the reporter recovers from it and ignores it, proceeding with its usual functionality for formatting a value.
1 parent 77ae86f commit d669b04

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

cmp/compare_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"crypto/md5"
1010
"encoding/json"
11+
"errors"
1112
"flag"
1213
"fmt"
1314
"io"
@@ -874,6 +875,18 @@ func reporterTests() []test {
874875
)
875876

876877
return []test{{
878+
label: label + "/PanicStringer",
879+
x: struct{ X fmt.Stringer }{struct{ fmt.Stringer }{nil}},
880+
y: struct{ X fmt.Stringer }{bytes.NewBuffer(nil)},
881+
wantEqual: false,
882+
reason: "panic from fmt.Stringer should not crash the reporter",
883+
}, {
884+
label: label + "/PanicError",
885+
x: struct{ X error }{struct{ error }{nil}},
886+
y: struct{ X error }{errors.New("")},
887+
wantEqual: false,
888+
reason: "panic from error should not crash the reporter",
889+
}, {
877890
label: label + "/AmbiguousType",
878891
x: foo1.Bar{},
879892
y: foo2.Bar{},

cmp/report_reflect.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,18 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind,
125125
// implementations crash when doing so.
126126
if (t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface) || !v.IsNil() {
127127
var prefix, strVal string
128-
switch v := v.Interface().(type) {
129-
case error:
130-
prefix, strVal = "e", v.Error()
131-
case fmt.Stringer:
132-
prefix, strVal = "s", v.String()
133-
}
128+
func() {
129+
// Swallow and ignore any panics from String or Error.
130+
defer func() { recover() }()
131+
switch v := v.Interface().(type) {
132+
case error:
133+
strVal = v.Error()
134+
prefix = "e"
135+
case fmt.Stringer:
136+
strVal = v.String()
137+
prefix = "s"
138+
}
139+
}()
134140
if prefix != "" {
135141
maxLen := len(strVal)
136142
if opts.LimitVerbosity {

cmp/testdata/diffs

+12
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@
252252
})),
253253
}
254254
>>> TestDiff/Transformer/AcyclicString
255+
<<< TestDiff/Reporter/PanicStringer
256+
struct{ X fmt.Stringer }{
257+
- X: struct{ fmt.Stringer }{},
258+
+ X: s"",
259+
}
260+
>>> TestDiff/Reporter/PanicStringer
261+
<<< TestDiff/Reporter/PanicError
262+
struct{ X error }{
263+
- X: struct{ error }{},
264+
+ X: e"",
265+
}
266+
>>> TestDiff/Reporter/PanicError
255267
<<< TestDiff/Reporter/AmbiguousType
256268
interface{}(
257269
- "github.com/google/go-cmp/cmp/internal/teststructs/foo1".Bar{},

0 commit comments

Comments
 (0)