Fix a crash condition when AnErr is used with a nil interface
This commit is contained in:
parent
505b18daf2
commit
68a3fd989d
9
array.go
9
array.go
|
@ -93,8 +93,7 @@ func (a *Array) RawJSON(val []byte) *Array {
|
|||
|
||||
// Err serializes and appends the err to the array.
|
||||
func (a *Array) Err(err error) *Array {
|
||||
marshaled := ErrorMarshalFunc(err)
|
||||
switch m := marshaled.(type) {
|
||||
switch m := ErrorMarshalFunc(err).(type) {
|
||||
case LogObjectMarshaler:
|
||||
e := newEvent(nil, 0)
|
||||
e.buf = e.buf[:0]
|
||||
|
@ -102,7 +101,11 @@ func (a *Array) Err(err error) *Array {
|
|||
a.buf = append(enc.AppendArrayDelim(a.buf), e.buf...)
|
||||
putEvent(e)
|
||||
case error:
|
||||
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
a.buf = enc.AppendNil(enc.AppendArrayDelim(a.buf))
|
||||
} else {
|
||||
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m.Error())
|
||||
}
|
||||
case string:
|
||||
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m)
|
||||
default:
|
||||
|
|
18
context.go
18
context.go
|
@ -104,14 +104,17 @@ func (c Context) RawJSON(key string, b []byte) Context {
|
|||
|
||||
// AnErr adds the field key with serialized err to the logger context.
|
||||
func (c Context) AnErr(key string, err error) Context {
|
||||
marshaled := ErrorMarshalFunc(err)
|
||||
switch m := marshaled.(type) {
|
||||
switch m := ErrorMarshalFunc(err).(type) {
|
||||
case nil:
|
||||
return c
|
||||
case LogObjectMarshaler:
|
||||
return c.Object(key, m)
|
||||
case error:
|
||||
return c.Str(key, m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
return c
|
||||
} else {
|
||||
return c.Str(key, m.Error())
|
||||
}
|
||||
case string:
|
||||
return c.Str(key, m)
|
||||
default:
|
||||
|
@ -124,12 +127,15 @@ func (c Context) AnErr(key string, err error) Context {
|
|||
func (c Context) Errs(key string, errs []error) Context {
|
||||
arr := Arr()
|
||||
for _, err := range errs {
|
||||
marshaled := ErrorMarshalFunc(err)
|
||||
switch m := marshaled.(type) {
|
||||
switch m := ErrorMarshalFunc(err).(type) {
|
||||
case LogObjectMarshaler:
|
||||
arr = arr.Object(m)
|
||||
case error:
|
||||
arr = arr.Str(m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
arr = arr.Interface(nil)
|
||||
} else {
|
||||
arr = arr.Str(m.Error())
|
||||
}
|
||||
case string:
|
||||
arr = arr.Str(m)
|
||||
default:
|
||||
|
|
10
event.go
10
event.go
|
@ -280,7 +280,11 @@ func (e *Event) AnErr(key string, err error) *Event {
|
|||
case LogObjectMarshaler:
|
||||
return e.Object(key, m)
|
||||
case error:
|
||||
return e.Str(key, m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
return e
|
||||
} else {
|
||||
return e.Str(key, m.Error())
|
||||
}
|
||||
case string:
|
||||
return e.Str(key, m)
|
||||
default:
|
||||
|
@ -330,7 +334,9 @@ func (e *Event) Err(err error) *Event {
|
|||
case LogObjectMarshaler:
|
||||
e.Object(ErrorStackFieldName, m)
|
||||
case error:
|
||||
e.Str(ErrorStackFieldName, m.Error())
|
||||
if m != nil && !isNilValue(m) {
|
||||
e.Str(ErrorStackFieldName, m.Error())
|
||||
}
|
||||
case string:
|
||||
e.Str(ErrorStackFieldName, m)
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// +build !binary_log
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type nilError struct{}
|
||||
|
||||
func (nilError) Error() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestEvent_AnErr(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
want string
|
||||
}{
|
||||
{"nil", nil, `{}`},
|
||||
{"error", errors.New("test"), `{"err":"test"}`},
|
||||
{"nil interface", func() *nilError { return nil }(), `{}`},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
e := newEvent(levelWriterAdapter{&buf}, DebugLevel)
|
||||
e.AnErr("err", tt.err)
|
||||
_ = e.write()
|
||||
if got, want := strings.TrimSpace(buf.String()), tt.want; got != want {
|
||||
t.Errorf("Event.AnErr() = %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
23
fields.go
23
fields.go
|
@ -4,8 +4,13 @@ import (
|
|||
"net"
|
||||
"sort"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func isNilValue(i interface{}) bool {
|
||||
return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
|
||||
}
|
||||
|
||||
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||
keys := make([]string, 0, len(fields))
|
||||
for key := range fields {
|
||||
|
@ -29,8 +34,7 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
|||
case []byte:
|
||||
dst = enc.AppendBytes(dst, val)
|
||||
case error:
|
||||
marshaled := ErrorMarshalFunc(val)
|
||||
switch m := marshaled.(type) {
|
||||
switch m := ErrorMarshalFunc(val).(type) {
|
||||
case LogObjectMarshaler:
|
||||
e := newEvent(nil, 0)
|
||||
e.buf = e.buf[:0]
|
||||
|
@ -38,7 +42,11 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
|||
dst = append(dst, e.buf...)
|
||||
putEvent(e)
|
||||
case error:
|
||||
dst = enc.AppendString(dst, m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
dst = enc.AppendNil(dst)
|
||||
} else {
|
||||
dst = enc.AppendString(dst, m.Error())
|
||||
}
|
||||
case string:
|
||||
dst = enc.AppendString(dst, m)
|
||||
default:
|
||||
|
@ -47,8 +55,7 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
|||
case []error:
|
||||
dst = enc.AppendArrayStart(dst)
|
||||
for i, err := range val {
|
||||
marshaled := ErrorMarshalFunc(err)
|
||||
switch m := marshaled.(type) {
|
||||
switch m := ErrorMarshalFunc(err).(type) {
|
||||
case LogObjectMarshaler:
|
||||
e := newEvent(nil, 0)
|
||||
e.buf = e.buf[:0]
|
||||
|
@ -56,7 +63,11 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
|||
dst = append(dst, e.buf...)
|
||||
putEvent(e)
|
||||
case error:
|
||||
dst = enc.AppendString(dst, m.Error())
|
||||
if m == nil || isNilValue(m) {
|
||||
dst = enc.AppendNil(dst)
|
||||
} else {
|
||||
dst = enc.AppendString(dst, m.Error())
|
||||
}
|
||||
case string:
|
||||
dst = enc.AppendString(dst, m)
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue