diff --git a/misc_tests/jsoniter_float_test.go b/misc_tests/jsoniter_float_test.go index de7bc96..34edd4a 100644 --- a/misc_tests/jsoniter_float_test.go +++ b/misc_tests/jsoniter_float_test.go @@ -2,6 +2,7 @@ package misc_tests import ( "encoding/json" + "math" "testing" "github.com/json-iterator/go" @@ -77,6 +78,26 @@ func Test_read_number(t *testing.T) { should.Equal(`92233720368547758079223372036854775807`, string(val)) } +func Test_encode_inf(t *testing.T) { + should := require.New(t) + _, err := json.Marshal(math.Inf(1)) + should.Error(err) + _, err = jsoniter.Marshal(float32(math.Inf(1))) + should.Error(err) + _, err = jsoniter.Marshal(math.Inf(-1)) + should.Error(err) +} + +func Test_encode_nan(t *testing.T) { + should := require.New(t) + _, err := json.Marshal(math.NaN()) + should.Error(err) + _, err = jsoniter.Marshal(float32(math.NaN())) + should.Error(err) + _, err = jsoniter.Marshal(math.NaN()) + should.Error(err) +} + func Benchmark_jsoniter_float(b *testing.B) { b.ReportAllocs() input := []byte(`1.1123,`) diff --git a/stream_float.go b/stream_float.go index f318d2c..826aa59 100644 --- a/stream_float.go +++ b/stream_float.go @@ -1,6 +1,7 @@ package jsoniter import ( + "fmt" "math" "strconv" ) @@ -13,6 +14,10 @@ func init() { // WriteFloat32 write float32 to stream func (stream *Stream) WriteFloat32(val float32) { + if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) { + stream.Error = fmt.Errorf("unsupported value: %f", val) + return + } abs := math.Abs(float64(val)) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. @@ -26,6 +31,10 @@ func (stream *Stream) WriteFloat32(val float32) { // WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster func (stream *Stream) WriteFloat32Lossy(val float32) { + if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) { + stream.Error = fmt.Errorf("unsupported value: %f", val) + return + } if val < 0 { stream.writeByte('-') val = -val @@ -54,6 +63,10 @@ func (stream *Stream) WriteFloat32Lossy(val float32) { // WriteFloat64 write float64 to stream func (stream *Stream) WriteFloat64(val float64) { + if math.IsInf(val, 0) || math.IsNaN(val) { + stream.Error = fmt.Errorf("unsupported value: %f", val) + return + } abs := math.Abs(val) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. @@ -67,6 +80,10 @@ func (stream *Stream) WriteFloat64(val float64) { // WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster func (stream *Stream) WriteFloat64Lossy(val float64) { + if math.IsInf(val, 0) || math.IsNaN(val) { + stream.Error = fmt.Errorf("unsupported value: %f", val) + return + } if val < 0 { stream.writeByte('-') val = -val