summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-14 18:55:57 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-25 17:07:32 -0700
commite38edfa53173c054ff97a5c51f90df0da60f16f5 (patch)
tree81393740a92395bf18a7d9cd2d751f2c2df5db2e
parent051f966039028d257f27fc3a42c10cbff9f7c738 (diff)
jsonparse: Reword error messages to match encoding/json
-rw-r--r--ReleaseNotes.md3
-rw-r--r--compat/json/compat_test.go18
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/1071d2f6e5b5f7d32
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/6bced2300496f15c2
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/6daf2467420749672
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/7c3168c77fc059cb2
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/a955c588d78b5c3a2
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/cf667c6f1f3282c12
-rw-r--r--compat/json/testdata/fuzz/FuzzEquiv/ef2c8755a89034da2
-rw-r--r--internal/jsonparse/parse.go20
-rw-r--r--methods_test.go4
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`},