Fix a crash condition when AnErr is used with a nil interface
This commit is contained in:
parent
505b18daf2
commit
68a3fd989d
7
array.go
7
array.go
|
@ -93,8 +93,7 @@ func (a *Array) RawJSON(val []byte) *Array {
|
||||||
|
|
||||||
// Err serializes and appends the err to the array.
|
// Err serializes and appends the err to the array.
|
||||||
func (a *Array) Err(err error) *Array {
|
func (a *Array) Err(err error) *Array {
|
||||||
marshaled := ErrorMarshalFunc(err)
|
switch m := ErrorMarshalFunc(err).(type) {
|
||||||
switch m := marshaled.(type) {
|
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
e := newEvent(nil, 0)
|
e := newEvent(nil, 0)
|
||||||
e.buf = e.buf[: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...)
|
a.buf = append(enc.AppendArrayDelim(a.buf), e.buf...)
|
||||||
putEvent(e)
|
putEvent(e)
|
||||||
case error:
|
case 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())
|
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m)
|
a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m)
|
||||||
default:
|
default:
|
||||||
|
|
14
context.go
14
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.
|
// AnErr adds the field key with serialized err to the logger context.
|
||||||
func (c Context) AnErr(key string, err error) Context {
|
func (c Context) AnErr(key string, err error) Context {
|
||||||
marshaled := ErrorMarshalFunc(err)
|
switch m := ErrorMarshalFunc(err).(type) {
|
||||||
switch m := marshaled.(type) {
|
|
||||||
case nil:
|
case nil:
|
||||||
return c
|
return c
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
return c.Object(key, m)
|
return c.Object(key, m)
|
||||||
case error:
|
case error:
|
||||||
|
if m == nil || isNilValue(m) {
|
||||||
|
return c
|
||||||
|
} else {
|
||||||
return c.Str(key, m.Error())
|
return c.Str(key, m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
return c.Str(key, m)
|
return c.Str(key, m)
|
||||||
default:
|
default:
|
||||||
|
@ -124,12 +127,15 @@ func (c Context) AnErr(key string, err error) Context {
|
||||||
func (c Context) Errs(key string, errs []error) Context {
|
func (c Context) Errs(key string, errs []error) Context {
|
||||||
arr := Arr()
|
arr := Arr()
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
marshaled := ErrorMarshalFunc(err)
|
switch m := ErrorMarshalFunc(err).(type) {
|
||||||
switch m := marshaled.(type) {
|
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
arr = arr.Object(m)
|
arr = arr.Object(m)
|
||||||
case error:
|
case error:
|
||||||
|
if m == nil || isNilValue(m) {
|
||||||
|
arr = arr.Interface(nil)
|
||||||
|
} else {
|
||||||
arr = arr.Str(m.Error())
|
arr = arr.Str(m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
arr = arr.Str(m)
|
arr = arr.Str(m)
|
||||||
default:
|
default:
|
||||||
|
|
6
event.go
6
event.go
|
@ -280,7 +280,11 @@ func (e *Event) AnErr(key string, err error) *Event {
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
return e.Object(key, m)
|
return e.Object(key, m)
|
||||||
case error:
|
case error:
|
||||||
|
if m == nil || isNilValue(m) {
|
||||||
|
return e
|
||||||
|
} else {
|
||||||
return e.Str(key, m.Error())
|
return e.Str(key, m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
return e.Str(key, m)
|
return e.Str(key, m)
|
||||||
default:
|
default:
|
||||||
|
@ -330,7 +334,9 @@ func (e *Event) Err(err error) *Event {
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
e.Object(ErrorStackFieldName, m)
|
e.Object(ErrorStackFieldName, m)
|
||||||
case error:
|
case error:
|
||||||
|
if m != nil && !isNilValue(m) {
|
||||||
e.Str(ErrorStackFieldName, m.Error())
|
e.Str(ErrorStackFieldName, m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
e.Str(ErrorStackFieldName, m)
|
e.Str(ErrorStackFieldName, m)
|
||||||
default:
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
19
fields.go
19
fields.go
|
@ -4,8 +4,13 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func isNilValue(i interface{}) bool {
|
||||||
|
return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
|
||||||
|
}
|
||||||
|
|
||||||
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||||
keys := make([]string, 0, len(fields))
|
keys := make([]string, 0, len(fields))
|
||||||
for key := range fields {
|
for key := range fields {
|
||||||
|
@ -29,8 +34,7 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||||
case []byte:
|
case []byte:
|
||||||
dst = enc.AppendBytes(dst, val)
|
dst = enc.AppendBytes(dst, val)
|
||||||
case error:
|
case error:
|
||||||
marshaled := ErrorMarshalFunc(val)
|
switch m := ErrorMarshalFunc(val).(type) {
|
||||||
switch m := marshaled.(type) {
|
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
e := newEvent(nil, 0)
|
e := newEvent(nil, 0)
|
||||||
e.buf = e.buf[:0]
|
e.buf = e.buf[:0]
|
||||||
|
@ -38,7 +42,11 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||||
dst = append(dst, e.buf...)
|
dst = append(dst, e.buf...)
|
||||||
putEvent(e)
|
putEvent(e)
|
||||||
case error:
|
case error:
|
||||||
|
if m == nil || isNilValue(m) {
|
||||||
|
dst = enc.AppendNil(dst)
|
||||||
|
} else {
|
||||||
dst = enc.AppendString(dst, m.Error())
|
dst = enc.AppendString(dst, m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
dst = enc.AppendString(dst, m)
|
dst = enc.AppendString(dst, m)
|
||||||
default:
|
default:
|
||||||
|
@ -47,8 +55,7 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||||
case []error:
|
case []error:
|
||||||
dst = enc.AppendArrayStart(dst)
|
dst = enc.AppendArrayStart(dst)
|
||||||
for i, err := range val {
|
for i, err := range val {
|
||||||
marshaled := ErrorMarshalFunc(err)
|
switch m := ErrorMarshalFunc(err).(type) {
|
||||||
switch m := marshaled.(type) {
|
|
||||||
case LogObjectMarshaler:
|
case LogObjectMarshaler:
|
||||||
e := newEvent(nil, 0)
|
e := newEvent(nil, 0)
|
||||||
e.buf = e.buf[:0]
|
e.buf = e.buf[:0]
|
||||||
|
@ -56,7 +63,11 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte {
|
||||||
dst = append(dst, e.buf...)
|
dst = append(dst, e.buf...)
|
||||||
putEvent(e)
|
putEvent(e)
|
||||||
case error:
|
case error:
|
||||||
|
if m == nil || isNilValue(m) {
|
||||||
|
dst = enc.AppendNil(dst)
|
||||||
|
} else {
|
||||||
dst = enc.AppendString(dst, m.Error())
|
dst = enc.AppendString(dst, m.Error())
|
||||||
|
}
|
||||||
case string:
|
case string:
|
||||||
dst = enc.AppendString(dst, m)
|
dst = enc.AppendString(dst, m)
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue