From 3b4ca665fbe89bdf44560454684bb6829070d7f4 Mon Sep 17 00:00:00 2001
From: Luke Shumaker <lukeshu@lukeshu.com>
Date: Fri, 24 Feb 2023 09:20:15 -0700
Subject: jsonparse: Fix a bug allowing a trailing comma in objects

---
 internal/jsonparse/parse.go      | 33 ++++++++++++++++++++++-----------
 internal/jsonparse/parse_test.go | 14 +++++++-------
 2 files changed, 29 insertions(+), 18 deletions(-)

(limited to 'internal/jsonparse')

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
-- 
cgit v1.2.3-2-g168b