From 6b6938829d6156d7b9825f83eec757f0f571c981 Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Tue, 18 Jul 2017 22:19:52 +0800 Subject: [PATCH] #136 strconv.ParseFloat can not validate 1. , added extra validation for this special case --- feature_iter_float.go | 16 ++++++++++++++++ feature_iter_skip_strict.go | 13 +++++++++++-- jsoniter_invalid_test.go | 18 ++++++++++++++++++ skip_tests/number/inputs.go | 1 + 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/feature_iter_float.go b/feature_iter_float.go index 2833f4e..956cf82 100644 --- a/feature_iter_float.go +++ b/feature_iter_float.go @@ -1,6 +1,7 @@ package jsoniter import ( + "fmt" "io" "math/big" "strconv" @@ -129,6 +130,9 @@ non_decimal_loop: if c == '.' { i++ decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat32SlowPath() + } for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] @@ -197,6 +201,10 @@ func (iter *Iterator) readFloat32SlowPath() (ret float32) { iter.ReportError("readFloat32SlowPath", "-- is not valid") return } + if str[len(str)-1] == '.' { + iter.ReportError("readFloat32SlowPath", "dot can not be last character") + return + } val, err := strconv.ParseFloat(str, 32) if err != nil { iter.Error = err @@ -270,6 +278,9 @@ non_decimal_loop: if c == '.' { i++ decimalPlaces := 0 + if i == iter.tail { + return iter.readFloat64SlowPath() + } for ; i < iter.tail; i++ { c = iter.buf[i] ind := floatDigits[c] @@ -309,10 +320,15 @@ func (iter *Iterator) readFloat64SlowPath() (ret float64) { iter.ReportError("readFloat64SlowPath", "-- is not valid") return } + if str[len(str)-1] == '.' { + iter.ReportError("readFloat64SlowPath", "dot can not be last character") + return + } val, err := strconv.ParseFloat(str, 64) if err != nil { iter.Error = err return } + fmt.Println(str) return val } diff --git a/feature_iter_skip_strict.go b/feature_iter_skip_strict.go index 0477ba2..c282960 100644 --- a/feature_iter_skip_strict.go +++ b/feature_iter_skip_strict.go @@ -21,9 +21,18 @@ func (iter *Iterator) trySkipNumber() bool { if dotFound { iter.ReportError("validateNumber", `more than one dot found in number`) return true // already failed - } else { - dotFound = true } + if i+1 == iter.tail { + return false + } + c = iter.buf[i+1] + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + default: + iter.ReportError("validateNumber", `missing digit after dot`) + return true // already failed + } + dotFound = true default: switch c { case ',', ']', '}', ' ', '\t', '\n', '\r': diff --git a/jsoniter_invalid_test.go b/jsoniter_invalid_test.go index a26d7e2..a8d4a3c 100644 --- a/jsoniter_invalid_test.go +++ b/jsoniter_invalid_test.go @@ -111,3 +111,21 @@ func Test_empty_as_number(t *testing.T) { should.NotEqual(io.EOF, iter.Error) should.NotNil(iter.Error) } + +func Test_missing_digit_after_dot(t *testing.T) { + should := require.New(t) + iter := ParseString(ConfigDefault, `1.,`) + iter.Skip() + should.NotEqual(io.EOF, iter.Error) + should.NotNil(iter.Error) + v := float64(0) + should.NotNil(json.Unmarshal([]byte(`1.`), &v)) + iter = ParseString(ConfigDefault, `1.`) + iter.ReadFloat64() + should.NotEqual(io.EOF, iter.Error) + should.NotNil(iter.Error) + iter = ParseString(ConfigDefault, `1.`) + iter.ReadFloat32() + should.NotEqual(io.EOF, iter.Error) + should.NotNil(iter.Error) +} diff --git a/skip_tests/number/inputs.go b/skip_tests/number/inputs.go index a8553a3..4eaca2f 100644 --- a/skip_tests/number/inputs.go +++ b/skip_tests/number/inputs.go @@ -13,4 +13,5 @@ var inputs = []string{ "1E1", // valid, e or E "1ee1", // invalid "100a", // invalid + "10.", // invalid }