From baa31cfa8565110ee2db8c5a483f928697f5305c Mon Sep 17 00:00:00 2001 From: anthony <31537659+anthony92717773@users.noreply.github.com> Date: Wed, 31 Oct 2018 18:40:46 +0100 Subject: [PATCH] Fix nil pointer dereference when call Fields with a typed nil value (#112) --- fields.go | 96 ++++++++++++++++++++++++++++++++++++++++++++--------- log_test.go | 46 +++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 16 deletions(-) diff --git a/fields.go b/fields.go index b65885d..6b62ecc 100644 --- a/fields.go +++ b/fields.go @@ -99,37 +99,101 @@ func appendFields(dst []byte, fields map[string]interface{}) []byte { case time.Duration: dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger) case *string: - dst = enc.AppendString(dst, *val) + if val != nil { + dst = enc.AppendString(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *bool: - dst = enc.AppendBool(dst, *val) + if val != nil { + dst = enc.AppendBool(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *int: - dst = enc.AppendInt(dst, *val) + if val != nil { + dst = enc.AppendInt(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *int8: - dst = enc.AppendInt8(dst, *val) + if val != nil { + dst = enc.AppendInt8(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *int16: - dst = enc.AppendInt16(dst, *val) + if val != nil { + dst = enc.AppendInt16(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *int32: - dst = enc.AppendInt32(dst, *val) + if val != nil { + dst = enc.AppendInt32(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *int64: - dst = enc.AppendInt64(dst, *val) + if val != nil { + dst = enc.AppendInt64(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *uint: - dst = enc.AppendUint(dst, *val) + if val != nil { + dst = enc.AppendUint(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *uint8: - dst = enc.AppendUint8(dst, *val) + if val != nil { + dst = enc.AppendUint8(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *uint16: - dst = enc.AppendUint16(dst, *val) + if val != nil { + dst = enc.AppendUint16(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *uint32: - dst = enc.AppendUint32(dst, *val) + if val != nil { + dst = enc.AppendUint32(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *uint64: - dst = enc.AppendUint64(dst, *val) + if val != nil { + dst = enc.AppendUint64(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *float32: - dst = enc.AppendFloat32(dst, *val) + if val != nil { + dst = enc.AppendFloat32(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *float64: - dst = enc.AppendFloat64(dst, *val) + if val != nil { + dst = enc.AppendFloat64(dst, *val) + } else { + dst = enc.AppendNil(dst) + } case *time.Time: - dst = enc.AppendTime(dst, *val, TimeFieldFormat) + if val != nil { + dst = enc.AppendTime(dst, *val, TimeFieldFormat) + } else { + dst = enc.AppendNil(dst) + } case *time.Duration: - dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger) + if val != nil { + dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger) + } else { + dst = enc.AppendNil(dst) + } case []string: dst = enc.AppendStrings(dst, val) case []bool: diff --git a/log_test.go b/log_test.go index a4b66e4..3ae0238 100644 --- a/log_test.go +++ b/log_test.go @@ -164,6 +164,52 @@ func TestFieldsMapPnt(t *testing.T) { } } +func TestFieldsMapNilPnt(t *testing.T) { + var ( + stringPnt *string + boolPnt *bool + intPnt *int + int8Pnt *int8 + int16Pnt *int16 + int32Pnt *int32 + int64Pnt *int64 + uintPnt *uint + uint8Pnt *uint8 + uint16Pnt *uint16 + uint32Pnt *uint32 + uint64Pnt *uint64 + float32Pnt *float32 + float64Pnt *float64 + durPnt *time.Duration + timePnt *time.Time + ) + out := &bytes.Buffer{} + log := New(out) + fields := map[string]interface{}{ + "string": stringPnt, + "bool": boolPnt, + "int": intPnt, + "int8": int8Pnt, + "int16": int16Pnt, + "int32": int32Pnt, + "int64": int64Pnt, + "uint": uintPnt, + "uint8": uint8Pnt, + "uint16": uint16Pnt, + "uint32": uint32Pnt, + "uint64": uint64Pnt, + "float32": float32Pnt, + "float64": float64Pnt, + "dur": durPnt, + "time": timePnt, + } + + log.Log().Fields(fields).Msg("") + if got, want := decodeIfBinaryToString(out.Bytes()), `{"bool":null,"dur":null,"float32":null,"float64":null,"int":null,"int16":null,"int32":null,"int64":null,"int8":null,"string":null,"time":null,"uint":null,"uint16":null,"uint32":null,"uint64":null,"uint8":null}`+"\n"; got != want { + t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) + } +} + func TestFields(t *testing.T) { out := &bytes.Buffer{} log := New(out)