diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-14 18:55:57 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-25 17:07:32 -0700 |
commit | e38edfa53173c054ff97a5c51f90df0da60f16f5 (patch) | |
tree | 81393740a92395bf18a7d9cd2d751f2c2df5db2e | |
parent | 051f966039028d257f27fc3a42c10cbff9f7c738 (diff) |
jsonparse: Reword error messages to match encoding/json
-rw-r--r-- | ReleaseNotes.md | 3 | ||||
-rw-r--r-- | compat/json/compat_test.go | 18 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/1071d2f6e5b5f7d3 | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/6bced2300496f15c | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/6daf246742074967 | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/7c3168c77fc059cb | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/a955c588d78b5c3a | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/cf667c6f1f3282c1 | 2 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/ef2c8755a89034da | 2 | ||||
-rw-r--r-- | internal/jsonparse/parse.go | 20 | ||||
-rw-r--r-- | methods_test.go | 4 |
11 files changed, 47 insertions, 12 deletions
diff --git a/ReleaseNotes.md b/ReleaseNotes.md index af2adcc..1981678 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -14,6 +14,9 @@ then the first type error encountered is returned. This is consistent with the behavior of `encoding/json`. + - Change: Several error strings have been reworded to match + `encoding/json`. + - Bugfix: Decoder: If there is a syntax error in a byte that invalid UTF-8, include that byte value in the error message rather than including the U+FFFD Unicode replacement character. diff --git a/compat/json/compat_test.go b/compat/json/compat_test.go index 6aab103..cf9e359 100644 --- a/compat/json/compat_test.go +++ b/compat/json/compat_test.go @@ -188,6 +188,24 @@ func TestCompatUnmarshal(t *testing.T) { "obj-overflow": {In: `{"foo":"bar", "baz":2e308, "qux": "orb"}`, ExpOut: map[string]any{"foo": "bar", "baz": nil, "qux": "orb"}, ExpErr: `json: cannot unmarshal number 2e308 into Go value of type float64`}, "ary-overflow": {In: `["foo",2e308,"bar",3e308]`, ExpOut: []any{"foo", nil, "bar", nil}, ExpErr: `json: cannot unmarshal number 2e308 into Go value of type float64`}, "existing-overflow": {In: `2e308`, InPtr: func() any { x := 4; return &x }(), ExpOut: 4, ExpErr: `json: cannot unmarshal number 2e308 into Go value of type int`}, + // syntax error messages + "syntax-01": {In: `{}x`, ExpErr: `invalid character 'x' after top-level value`}, + "syntax-02": {In: `x`, ExpErr: `invalid character 'x' looking for beginning of value`}, + "syntax-03": {In: `{x`, ExpErr: `invalid character 'x' looking for beginning of object key string`}, + "syntax-04": {In: `{""x`, ExpErr: `invalid character 'x' after object key`}, + "syntax-05": {In: `{"":0x`, ExpErr: `invalid character 'x' after object key:value pair`}, + "syntax-06": {In: `[0x`, ExpErr: `invalid character 'x' after array element`}, + "syntax-07": {In: "\"\x01\"", ExpErr: `invalid character '\x01' in string literal`}, + "syntax-08": {In: `"\x`, ExpErr: `invalid character 'x' in string escape code`}, + "syntax-09": {In: `"\ux`, ExpErr: `invalid character 'x' in \u hexadecimal character escape`}, + "syntax-10": {In: `"\u0x`, ExpErr: `invalid character 'x' in \u hexadecimal character escape`}, + "syntax-11": {In: `"\u00x`, ExpErr: `invalid character 'x' in \u hexadecimal character escape`}, + "syntax-12": {In: `"\u000x`, ExpErr: `invalid character 'x' in \u hexadecimal character escape`}, + "syntax-13": {In: `-x`, ExpErr: `invalid character 'x' in numeric literal`}, + "syntax-14": {In: `0.x`, ExpErr: `invalid character 'x' after decimal point in numeric literal`}, + "syntax-15": {In: `1ex`, ExpErr: `invalid character 'x' in exponent of numeric literal`}, + "syntax-16": {In: `1e+x`, ExpErr: `invalid character 'x' in exponent of numeric literal`}, + "syntax-17": {In: `fx`, ExpErr: `invalid character 'x' in literal false (expecting 'a')`}, } for tcName, tc := range testcases { tc := tc diff --git a/compat/json/testdata/fuzz/FuzzEquiv/1071d2f6e5b5f7d3 b/compat/json/testdata/fuzz/FuzzEquiv/1071d2f6e5b5f7d3 new file mode 100644 index 0000000..1095817 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/1071d2f6e5b5f7d3 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0EA") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/6bced2300496f15c b/compat/json/testdata/fuzz/FuzzEquiv/6bced2300496f15c new file mode 100644 index 0000000..4bc9c61 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/6bced2300496f15c @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("{0") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/6daf246742074967 b/compat/json/testdata/fuzz/FuzzEquiv/6daf246742074967 new file mode 100644 index 0000000..b1c3453 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/6daf246742074967 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\"\\uX") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/7c3168c77fc059cb b/compat/json/testdata/fuzz/FuzzEquiv/7c3168c77fc059cb new file mode 100644 index 0000000..b95f079 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/7c3168c77fc059cb @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\"\x1e") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/a955c588d78b5c3a b/compat/json/testdata/fuzz/FuzzEquiv/a955c588d78b5c3a new file mode 100644 index 0000000..b135daa --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/a955c588d78b5c3a @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0.A") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/cf667c6f1f3282c1 b/compat/json/testdata/fuzz/FuzzEquiv/cf667c6f1f3282c1 new file mode 100644 index 0000000..f6ab571 --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/cf667c6f1f3282c1 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("\"\\0") diff --git a/compat/json/testdata/fuzz/FuzzEquiv/ef2c8755a89034da b/compat/json/testdata/fuzz/FuzzEquiv/ef2c8755a89034da new file mode 100644 index 0000000..7d9478d --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/ef2c8755a89034da @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0E+A") diff --git a/internal/jsonparse/parse.go b/internal/jsonparse/parse.go index 6432d75..c641f1b 100644 --- a/internal/jsonparse/parse.go +++ b/internal/jsonparse/parse.go @@ -619,7 +619,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { par.popState() return RuneTypeObjectEnd, nil default: - return RuneTypeError, fmt.Errorf("object: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf("invalid character %q looking for beginning of object key string", c) } case RuneTypeStringEnd: // waiting for ':' switch c { @@ -682,7 +682,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { case 0x0020 <= c && c <= 0x10FFFF: return RuneTypeStringChar, nil default: - return RuneTypeError, fmt.Errorf("string: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf("invalid character %q in string literal", c) } case RuneTypeStringEsc: // waiting for escape char switch c { @@ -692,26 +692,26 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { case 'u': return par.replaceState(RuneTypeStringEscU), nil default: - return RuneTypeError, fmt.Errorf("string backslash sequence: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf("invalid character %q in string escape code", c) } case RuneTypeStringEscU: if !isHex(c) { - return RuneTypeError, fmt.Errorf("string unicode sequence: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf(`invalid character %q in \u hexadecimal character escape`, c) } return par.replaceState(RuneTypeStringEscUA), nil case RuneTypeStringEscUA: if !isHex(c) { - return RuneTypeError, fmt.Errorf("string unicode sequence: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf(`invalid character %q in \u hexadecimal character escape`, c) } return par.replaceState(RuneTypeStringEscUB), nil case RuneTypeStringEscUB: if !isHex(c) { - return RuneTypeError, fmt.Errorf("string unicode sequence: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf(`invalid character %q in \u hexadecimal character escape`, c) } return par.replaceState(RuneTypeStringEscUC), nil case RuneTypeStringEscUC: if !isHex(c) { - return RuneTypeError, fmt.Errorf("string unicode sequence: unexpected character: %q", c) + return RuneTypeError, fmt.Errorf(`invalid character %q in \u hexadecimal character escape`, c) } par.replaceState(RuneTypeStringBeg) return RuneTypeStringEscUD, nil @@ -791,7 +791,7 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return par.replaceState(RuneTypeNumberFracDig), nil default: - return RuneTypeError, fmt.Errorf("invalid character %q in numeric literal", c) + return RuneTypeError, fmt.Errorf("invalid character %q after decimal point in numeric literal", c) } case RuneTypeNumberFracDig: // F switch c { @@ -810,14 +810,14 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return par.replaceState(RuneTypeNumberExpDig), nil default: - return RuneTypeError, fmt.Errorf("invalid character %q in numeric literal", c) + return RuneTypeError, fmt.Errorf("invalid character %q in exponent of numeric literal", c) } case RuneTypeNumberExpSign: // H switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return par.replaceState(RuneTypeNumberExpDig), nil default: - return RuneTypeError, fmt.Errorf("invalid character %q in numeric literal", c) + return RuneTypeError, fmt.Errorf("invalid character %q in exponent of numeric literal", c) } case RuneTypeNumberExpDig: // I switch c { diff --git a/methods_test.go b/methods_test.go index 64af28c..23a6c4f 100644 --- a/methods_test.go +++ b/methods_test.go @@ -304,8 +304,8 @@ func TestMethodsDecode(t *testing.T) { testcases := map[string]testcase{ "decode-basic": {In: `{}`, Obj: &tstDecoder{n: 2}}, "decode-basic-eof": {In: `{}`, Obj: &tstDecoder{n: 5}}, - "decode-syntax-error": {In: `{x}`, Obj: &tstDecoder{n: 5}, ExpectedErr: `json: v: syntax error at input byte 1: object: unexpected character: 'x'`}, - "unmarshal-syntax-error": {In: `{x}`, Obj: &strUnmarshaler{}, ExpectedErr: `json: v: syntax error at input byte 1: object: unexpected character: 'x'`}, + "decode-syntax-error": {In: `{x}`, Obj: &tstDecoder{n: 5}, ExpectedErr: `json: v: syntax error at input byte 1: invalid character 'x' looking for beginning of object key string`}, + "unmarshal-syntax-error": {In: `{x}`, Obj: &strUnmarshaler{}, ExpectedErr: `json: v: syntax error at input byte 1: invalid character 'x' looking for beginning of object key string`}, "decode-short": {In: `{}`, Obj: &tstDecoder{n: 1}, ExpectedErr: `json: v: cannot decode JSON object at input byte 0 into Go *lowmemjson_test.tstDecoder: did not consume entire object`}, "decode-err": {In: `{}`, Obj: &tstDecoder{err: "xxx"}, ExpectedErr: `json: v: cannot decode JSON object at input byte 0 into Go *lowmemjson_test.tstDecoder: xxx`}, "decode-err2": {In: `{}`, Obj: &tstDecoder{n: 1, err: "yyy"}, ExpectedErr: `json: v: cannot decode JSON object at input byte 0 into Go *lowmemjson_test.tstDecoder: yyy`}, |