浏览代码

#136 strconv.ParseFloat can not validate 1. , added extra validation for this special case

Tao Wen 8 年之前
父节点
当前提交
6b6938829d
共有 4 个文件被更改,包括 46 次插入2 次删除
  1. 16 0
      feature_iter_float.go
  2. 11 2
      feature_iter_skip_strict.go
  3. 18 0
      jsoniter_invalid_test.go
  4. 1 0
      skip_tests/number/inputs.go

+ 16 - 0
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
 }

+ 11 - 2
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':

+ 18 - 0
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)
+}

+ 1 - 0
skip_tests/number/inputs.go

@@ -13,4 +13,5 @@ var inputs = []string{
 	"1E1",   // valid, e or E
 	"1ee1",  // invalid
 	"100a",  // invalid
+	"10.",   // invalid
 }