From 70bea47cc0d8e7cac9c98fdd2bf8d0254e602be0 Mon Sep 17 00:00:00 2001 From: Ravi Raju Date: Fri, 13 Apr 2018 00:13:41 -0700 Subject: [PATCH] Fix for a bug in cbor decodeFloat (#51) --- array_test.go | 6 +++--- internal/cbor/decode_stream.go | 28 ++++++++++++++++------------ log_test.go | 12 ++++++------ 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/array_test.go b/array_test.go index 19bac56..66c6668 100644 --- a/array_test.go +++ b/array_test.go @@ -19,15 +19,15 @@ func TestArray(t *testing.T) { Uint16(8). Uint32(9). Uint64(10). - Float32(11). - Float64(12). + Float32(11.98122). + Float64(12.987654321). Str("a"). Bytes([]byte("b")). Hex([]byte{0x1f}). Time(time.Time{}). IPAddr(net.IP{192, 168, 0, 10}). Dur(0) - want := `[true,1,2,3,4,5,6,7,8,9,10,11,12,"a","b","1f","0001-01-01T00:00:00Z","192.168.0.10",0]` + want := `[true,1,2,3,4,5,6,7,8,9,10,11.98122,12.987654321,"a","b","1f","0001-01-01T00:00:00Z","192.168.0.10",0]` if got := decodeObjectToStr(a.write([]byte{})); got != want { t.Errorf("Array.write()\ngot: %s\nwant: %s", got, want) } diff --git a/internal/cbor/decode_stream.go b/internal/cbor/decode_stream.go index f1ff2a1..e3cf3b7 100644 --- a/internal/cbor/decode_stream.go +++ b/internal/cbor/decode_stream.go @@ -20,6 +20,9 @@ var decodeTimeZone *time.Location const hexTable = "0123456789abcdef" +const isFloat32 = 4 +const isFloat64 = 8 + func readNBytes(src *bufio.Reader, n int) []byte { ret := make([]byte, n) for i := 0; i < n; i++ { @@ -97,11 +100,11 @@ func decodeFloat(src *bufio.Reader) (float64, int) { pb := readNBytes(src, 4) switch string(pb) { case float32Nan: - return math.NaN(), 4 + return math.NaN(), isFloat32 case float32PosInfinity: - return math.Inf(0), 4 + return math.Inf(0), isFloat32 case float32NegInfinity: - return math.Inf(-1), 4 + return math.Inf(-1), isFloat32 } n := uint32(0) for i := 0; i < 4; i++ { @@ -109,16 +112,16 @@ func decodeFloat(src *bufio.Reader) (float64, int) { n += uint32(pb[i]) } val := math.Float32frombits(n) - return float64(val), 4 + return float64(val), isFloat32 case additionalTypeFloat64: pb := readNBytes(src, 8) switch string(pb) { case float64Nan: - return math.NaN(), 8 + return math.NaN(), isFloat64 case float64PosInfinity: - return math.Inf(0), 8 + return math.Inf(0), isFloat64 case float64NegInfinity: - return math.Inf(-1), 8 + return math.Inf(-1), isFloat64 } n := uint64(0) for i := 0; i < 8; i++ { @@ -126,14 +129,13 @@ func decodeFloat(src *bufio.Reader) (float64, int) { n += uint64(pb[i]) } val := math.Float64frombits(n) - return val, 8 + return val, isFloat64 } panic(fmt.Errorf("Invalid Additional Type: %d in decodeFloat", minor)) } func decodeStringComplex(dst []byte, s string, pos uint) []byte { i := int(pos) - const hex = "0123456789abcdef" start := 0 for i < len(s) { @@ -180,7 +182,7 @@ func decodeStringComplex(dst []byte, s string, pos uint) []byte { case '\t': dst = append(dst, '\\', 't') default: - dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF]) + dst = append(dst, '\\', 'u', '0', '0', hexTable[b>>4], hexTable[b&0xF]) } i++ start = i @@ -481,10 +483,12 @@ func decodeSimpleFloat(src *bufio.Reader) []byte { case math.IsInf(v, -1): return []byte("\"-Inf\"") } - if bc == 5 { + if bc == isFloat32 { ba = strconv.AppendFloat(ba, v, 'f', -1, 32) - } else { + } else if bc == isFloat64 { ba = strconv.AppendFloat(ba, v, 'f', -1, 64) + } else { + panic(fmt.Errorf("Invalid Float precision from decodeFloat: %d", bc)) } return ba default: diff --git a/log_test.go b/log_test.go index ebe716e..6503927 100644 --- a/log_test.go +++ b/log_test.go @@ -95,14 +95,14 @@ func TestWith(t *testing.T) { Uint16("uint16", 8). Uint32("uint32", 9). Uint64("uint64", 10). - Float32("float32", 11). - Float64("float64", 12). + Float32("float32", 11.101). + Float64("float64", 12.30303). Time("time", time.Time{}) _, file, line, _ := runtime.Caller(0) caller := fmt.Sprintf("%s:%d", file, line+3) log := ctx.Caller().Logger() log.Log().Msg("") - if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11,"float64":12,"time":"0001-01-01T00:00:00Z","caller":"`+caller+`"}`+"\n"; got != want { + if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"float32":11.101,"float64":12.30303,"time":"0001-01-01T00:00:00Z","caller":"`+caller+`"}`+"\n"; got != want { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) } } @@ -192,13 +192,13 @@ func TestFields(t *testing.T) { IPAddr("IPv6", net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}). MACAddr("Mac", net.HardwareAddr{0x00, 0x14, 0x22, 0x01, 0x23, 0x45}). IPPrefix("Prefix", net.IPNet{IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}). - Float32("float32", 11). - Float64("float64", 12). + Float32("float32", 11.1234). + Float64("float64", 12.321321321). Dur("dur", 1*time.Second). Time("time", time.Time{}). TimeDiff("diff", now, now.Add(-10*time.Second)). Msg("") - if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11,"float64":12,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want { + if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","bytes":"bar","hex":"12ef","json":{"some":"json"},"error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"IPv4":"192.168.0.100","IPv6":"2001:db8:85a3::8a2e:370:7334","Mac":"00:14:22:01:23:45","Prefix":"192.168.0.100/24","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000}`+"\n"; got != want { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) } }