diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-25 20:59:32 -0700 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-02-25 20:59:32 -0700 |
commit | 108100f782ab96dc0e68cfbcbc7595c7c04f313c (patch) | |
tree | 3a3ccc02a39edad8aa4116890e6070bd18d921ef | |
parent | 0fa9f8b14f04f4b0099f038cc43e4cef57a155a1 (diff) | |
parent | 3b4ca665fbe89bdf44560454684bb6829070d7f4 (diff) |
Merge branch 'lukeshu/syntax'
-rw-r--r-- | ReleaseNotes.md | 3 | ||||
-rw-r--r-- | compat/json/compat_test.go | 1 | ||||
-rw-r--r-- | compat/json/testdata/fuzz/FuzzEquiv/f9afef161f73f7cf | 2 | ||||
-rw-r--r-- | internal/jsonparse/parse.go | 33 | ||||
-rw-r--r-- | internal/jsonparse/parse_test.go | 14 |
5 files changed, 35 insertions, 18 deletions
diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 71973aa..be5b8ff 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -37,6 +37,9 @@ now reflect the `InvalidUTF8` setting, rather than simply saying "unflushed unicode garbage". + - Bugfix: No longer allows a comma after the last key:value pair in + an object. + # v0.3.7 (2023-02-20) Theme: Fixes from fuzzing (part 1?) diff --git a/compat/json/compat_test.go b/compat/json/compat_test.go index 3de48f7..af92093 100644 --- a/compat/json/compat_test.go +++ b/compat/json/compat_test.go @@ -196,6 +196,7 @@ func TestCompatUnmarshal(t *testing.T) { "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-18": {In: `{"":0,}`, ExpErr: `invalid character '}' 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`}, diff --git a/compat/json/testdata/fuzz/FuzzEquiv/f9afef161f73f7cf b/compat/json/testdata/fuzz/FuzzEquiv/f9afef161f73f7cf new file mode 100644 index 0000000..6618d0f --- /dev/null +++ b/compat/json/testdata/fuzz/FuzzEquiv/f9afef161f73f7cf @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("{\"\":{},}") diff --git a/internal/jsonparse/parse.go b/internal/jsonparse/parse.go index 5547df4..ce71a65 100644 --- a/internal/jsonparse/parse.go +++ b/internal/jsonparse/parse.go @@ -279,7 +279,8 @@ type Parser struct { // rule; they need some special assignments: // // { object: waiting for key to start or '}' - // » object: reading key / waiting for colon + // } object: waiting for key to start + // : object: reading key / waiting for colon // o object: reading value / waiting for ',' or '}' // // [ array: waiting for item to start or ']' @@ -298,17 +299,17 @@ type Parser struct { // stack processed // ? // { { - // »" {" - // »" {"x - // » {"x" + // :" {" + // :" {"x + // : {"x" // o? {"x": // o" {"x":" // o" {"x":"y // o {"x":"y" - // { {"x":"y", - // »" {"x":"y"," - // »" {"x":"y","a - // » {"x":"y","a" + // } {"x":"y", + // :" {"x":"y"," + // :" {"x":"y","a + // : {"x":"y","a" // o? {"x":"y","a": // o" {"x":"y","a":" // o" {"x":"y","a":"b @@ -627,7 +628,7 @@ func (par *Parser) HandleRune(c rune, isRune bool) (RuneType, error) { case 0x0020, 0x000A, 0x000D, 0x0009: return RuneTypeSpace, nil case '"': - par.replaceState(RuneTypeStringEnd) + par.replaceState(RuneTypeObjectColon) return par.pushState(RuneTypeStringBeg), nil case '}': par.popState() @@ -635,7 +636,17 @@ func (par *Parser) HandleRune(c rune, isRune bool) (RuneType, error) { default: return RuneTypeError, &InvalidCharacterError{c, isRune, "looking for beginning of object key string"} } - case RuneTypeStringEnd: // waiting for ':' + case RuneTypeObjectEnd: // waiting for key to start + switch c { + case 0x0020, 0x000A, 0x000D, 0x0009: + return RuneTypeSpace, nil + case '"': + par.replaceState(RuneTypeObjectColon) + return par.pushState(RuneTypeStringBeg), nil + default: + return RuneTypeError, &InvalidCharacterError{c, isRune, "looking for beginning of object key string"} + } + case RuneTypeObjectColon: // waiting for ':' switch c { case 0x0020, 0x000A, 0x000D, 0x0009: return RuneTypeSpace, nil @@ -651,7 +662,7 @@ func (par *Parser) HandleRune(c rune, isRune bool) (RuneType, error) { case 0x0020, 0x000A, 0x000D, 0x0009: return RuneTypeSpace, nil case ',': - par.replaceState(RuneTypeObjectBeg) + par.replaceState(RuneTypeObjectEnd) return RuneTypeObjectComma, nil case '}': par.popState() diff --git a/internal/jsonparse/parse_test.go b/internal/jsonparse/parse_test.go index acb43e8..fe94c58 100644 --- a/internal/jsonparse/parse_test.go +++ b/internal/jsonparse/parse_test.go @@ -24,17 +24,17 @@ func TestParserHandleRune(t *testing.T) { // st,// processed `?`, `{`, // { - `»"`, // {" - `»"`, // {"x - `»`, // {"x" + `:"`, // {" + `:"`, // {"x + `:`, // {"x" `o?`, // {"x": `o"`, // {"x":" `o"`, // {"x":"y `o`, // {"x":"y" - `{`, // {"x":"y", - `»"`, // {"x":"y"," - `»"`, // {"x":"y","a - `»`, // {"x":"y","a" + `}`, // {"x":"y", + `:"`, // {"x":"y"," + `:"`, // {"x":"y","a + `:`, // {"x":"y","a" `o?`, // {"x":"y","a": `o"`, // {"x":"y","a":" `o"`, // {"x":"y","a":"b |