1
0
mirror of https://github.com/json-iterator/go.git synced 2025-02-01 19:14:29 +02:00

#138 fix - without following digits; fix 1.e1

This commit is contained in:
Tao Wen 2017-07-18 23:48:40 +08:00
parent 17a26a6e20
commit f705934fbf
3 changed files with 61 additions and 80 deletions

View File

@ -4,6 +4,7 @@ import (
"io" "io"
"math/big" "math/big"
"strconv" "strconv"
"strings"
"unsafe" "unsafe"
) )
@ -192,16 +193,9 @@ func (iter *Iterator) readFloat32SlowPath() (ret float32) {
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
return return
} }
if len(str) == 0 { errMsg := validateFloat(str)
iter.ReportError("readFloat32SlowPath", "empty number") if errMsg != "" {
return iter.ReportError("readFloat32SlowPath", errMsg)
}
if str[0] == '-' {
iter.ReportError("readFloat32SlowPath", "-- is not valid")
return
}
if str[len(str)-1] == '.' {
iter.ReportError("readFloat32SlowPath", "dot can not be last character")
return return
} }
val, err := strconv.ParseFloat(str, 32) val, err := strconv.ParseFloat(str, 32)
@ -311,16 +305,9 @@ func (iter *Iterator) readFloat64SlowPath() (ret float64) {
if iter.Error != nil && iter.Error != io.EOF { if iter.Error != nil && iter.Error != io.EOF {
return return
} }
if len(str) == 0 { errMsg := validateFloat(str)
iter.ReportError("readFloat64SlowPath", "empty number") if errMsg != "" {
return iter.ReportError("readFloat64SlowPath", errMsg)
}
if str[0] == '-' {
iter.ReportError("readFloat64SlowPath", "-- is not valid")
return
}
if str[len(str)-1] == '.' {
iter.ReportError("readFloat64SlowPath", "dot can not be last character")
return return
} }
val, err := strconv.ParseFloat(str, 64) val, err := strconv.ParseFloat(str, 64)
@ -330,3 +317,25 @@ func (iter *Iterator) readFloat64SlowPath() (ret float64) {
} }
return val return val
} }
func validateFloat(str string) string {
// strconv.ParseFloat is not validating `1.` or `1.e1`
if len(str) == 0 {
return "empty number"
}
if str[0] == '-' {
return "-- is not valid"
}
dotPos := strings.IndexByte(str, '.')
if dotPos != -1 {
if dotPos == len(str)-1 {
return "dot can not be last character"
}
switch str[dotPos+1] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
return "missing digit after dot"
}
}
return ""
}

View File

@ -36,6 +36,9 @@ func (iter *Iterator) trySkipNumber() bool {
default: default:
switch c { switch c {
case ',', ']', '}', ' ', '\t', '\n', '\r': case ',', ']', '}', ' ', '\t', '\n', '\r':
if iter.head == i {
return false // if - without following digits
}
iter.head = i iter.head = i
return true // must be valid return true // must be valid
} }

View File

@ -68,64 +68,33 @@ func Test_invalid_array_input(t *testing.T) {
should.NotNil(Unmarshal(input, &obj)) should.NotNil(Unmarshal(input, &obj))
} }
func Test_double_negative(t *testing.T) { func Test_invalid_float(t *testing.T) {
should := require.New(t) inputs := []string{
var v interface{} `1.e1`, // dot without following digit
should.NotNil(json.Unmarshal([]byte(`--2`), &v)) `1.`, // dot can not be the last char
var vFloat64 float64 ``, // empty number
should.NotNil(UnmarshalFromString(`--2`, &vFloat64)) `01`, // extra leading zero
var vFloat32 float32 `-`, // negative without digit
should.NotNil(UnmarshalFromString(`--2`, &vFloat32)) `--`, // double negative
var vInt int `--2`, // double negative
should.NotNil(UnmarshalFromString(`--2`, &vInt)) }
iter := ParseString(ConfigDefault, `--2`) for _, input := range inputs {
iter.Skip() t.Run(input, func(t *testing.T) {
should.NotEqual(io.EOF, iter.Error) should := require.New(t)
should.NotNil(iter.Error) iter := ParseString(ConfigDefault, input+",")
} iter.Skip()
should.NotEqual(io.EOF, iter.Error)
func Test_leading_zero(t *testing.T) { should.NotNil(iter.Error)
should := require.New(t) v := float64(0)
var v interface{} should.NotNil(json.Unmarshal([]byte(input), &v))
should.NotNil(json.Unmarshal([]byte(`01`), &v)) iter = ParseString(ConfigDefault, input+",")
var vFloat64 float64 iter.ReadFloat64()
should.NotNil(UnmarshalFromString(`01`, &vFloat64)) should.NotEqual(io.EOF, iter.Error)
var vFloat32 float32 should.NotNil(iter.Error)
should.NotNil(UnmarshalFromString(`01`, &vFloat32)) iter = ParseString(ConfigDefault, input+",")
var vInt int iter.ReadFloat32()
should.NotNil(UnmarshalFromString(`01`, &vInt)) should.NotEqual(io.EOF, iter.Error)
iter := ParseString(ConfigDefault, `01,`) should.NotNil(iter.Error)
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)
}
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)
} }