Pārlūkot izejas kodu

#135 fix leading zero

Tao Wen 8 gadi atpakaļ
vecāks
revīzija
18d6ae2668
3 mainītis faili ar 97 papildinājumiem un 1 dzēšanām
  1. 60 0
      feature_iter_float.go
  2. 4 1
      feature_iter_skip.go
  3. 33 0
      jsoniter_invalid_test.go

+ 60 - 0
feature_iter_float.go

@@ -78,6 +78,35 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
 	value := uint64(0)
 	c := byte(' ')
 	i := iter.head
+	// first char
+	if i == iter.tail {
+		return iter.readFloat32SlowPath()
+	}
+	c = iter.buf[i]
+	i++
+	ind := floatDigits[c]
+	switch ind {
+	case invalidCharForNumber:
+		return iter.readFloat32SlowPath()
+	case endOfNumber:
+		iter.ReportError("readFloat32", "empty number")
+		return
+	case dotInNumber:
+		iter.ReportError("readFloat32", "leading dot is invalid")
+		return
+	case 0:
+		if i == iter.tail {
+			return iter.readFloat32SlowPath()
+		}
+		c = iter.buf[i]
+		switch c {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			iter.ReportError("readFloat32", "leading zero is invalid")
+			return
+		}
+	}
+	value = uint64(ind)
+	// chars before dot
 non_decimal_loop:
 	for ; i < iter.tail; i++ {
 		c = iter.buf[i]
@@ -96,6 +125,7 @@ non_decimal_loop:
 		}
 		value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
 	}
+	// chars after dot
 	if c == '.' {
 		i++
 		decimalPlaces := 0
@@ -189,6 +219,35 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
 	value := uint64(0)
 	c := byte(' ')
 	i := iter.head
+	// first char
+	if i == iter.tail {
+		return iter.readFloat64SlowPath()
+	}
+	c = iter.buf[i]
+	i++
+	ind := floatDigits[c]
+	switch ind {
+	case invalidCharForNumber:
+		return iter.readFloat64SlowPath()
+	case endOfNumber:
+		iter.ReportError("readFloat64", "empty number")
+		return
+	case dotInNumber:
+		iter.ReportError("readFloat64", "leading dot is invalid")
+		return
+	case 0:
+		if i == iter.tail {
+			return iter.readFloat64SlowPath()
+		}
+		c = iter.buf[i]
+		switch c {
+		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+			iter.ReportError("readFloat64", "leading zero is invalid")
+			return
+		}
+	}
+	value = uint64(ind)
+	// chars before dot
 non_decimal_loop:
 	for ; i < iter.tail; i++ {
 		c = iter.buf[i]
@@ -207,6 +266,7 @@ non_decimal_loop:
 		}
 		value = (value << 3) + (value << 1) + uint64(ind) // value = value * 10 + ind;
 	}
+	// chars after dot
 	if c == '.' {
 		i++
 		decimalPlaces := 0

+ 4 - 1
feature_iter_skip.go

@@ -77,7 +77,10 @@ func (iter *Iterator) Skip() {
 		iter.skipThreeBytes('r', 'u', 'e') // true
 	case 'f':
 		iter.skipFourBytes('a', 'l', 's', 'e') // false
-	case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+	case '0':
+		iter.unreadByte()
+		iter.ReadFloat32()
+	case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
 		iter.skipNumber()
 	case '[':
 		iter.skipArray()

+ 33 - 0
jsoniter_invalid_test.go

@@ -4,6 +4,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"testing"
 	"encoding/json"
+	"io"
 )
 
 func Test_missing_object_end(t *testing.T) {
@@ -77,4 +78,36 @@ func Test_double_negative(t *testing.T) {
 	should.NotNil(UnmarshalFromString(`--2`, &vFloat32))
 	var vInt int
 	should.NotNil(UnmarshalFromString(`--2`, &vInt))
+	iter := ParseString(ConfigDefault, `--2`)
+	iter.Skip()
+	should.NotEqual(io.EOF, iter.Error)
+	should.NotNil(iter.Error)
 }
+
+func Test_leading_zero(t *testing.T) {
+	should := require.New(t)
+	var v interface{}
+	should.NotNil(json.Unmarshal([]byte(`01`), &v))
+	var vFloat64 float64
+	should.NotNil(UnmarshalFromString(`01`, &vFloat64))
+	var vFloat32 float32
+	should.NotNil(UnmarshalFromString(`01`, &vFloat32))
+	var vInt int
+	should.NotNil(UnmarshalFromString(`01`, &vInt))
+	iter := ParseString(ConfigDefault, `01,`)
+	iter.Skip()
+	should.NotEqual(io.EOF, iter.Error)
+	should.NotNil(iter.Error)
+}
+
+func Test_empty_as_number(t *testing.T) {
+	should := require.New(t)
+	iter := ParseString(ConfigDefault, `,`)
+	iter.ReadFloat64()
+	should.NotEqual(io.EOF, iter.Error)
+	should.NotNil(iter.Error)
+	iter = ParseString(ConfigDefault, `,`)
+	iter.ReadFloat32()
+	should.NotEqual(io.EOF, iter.Error)
+	should.NotNil(iter.Error)
+}