summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/json/decoder.py7
-rw-r--r--Lib/test/test_json/test_fail.py8
-rw-r--r--Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst2
-rw-r--r--Modules/_json.c14
4 files changed, 28 insertions, 3 deletions
diff --git a/Lib/json/decoder.py b/Lib/json/decoder.py
index c5d9ae2..d69a45d 100644
--- a/Lib/json/decoder.py
+++ b/Lib/json/decoder.py
@@ -200,10 +200,13 @@ def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook,
break
elif nextchar != ',':
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
+ comma_idx = end - 1
end = _w(s, end).end()
nextchar = s[end:end + 1]
end += 1
if nextchar != '"':
+ if nextchar == '}':
+ raise JSONDecodeError("Illegal trailing comma before end of object", s, comma_idx)
raise JSONDecodeError(
"Expecting property name enclosed in double quotes", s, end - 1)
if object_pairs_hook is not None:
@@ -240,13 +243,17 @@ def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
break
elif nextchar != ',':
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
+ comma_idx = end - 1
try:
if s[end] in _ws:
end += 1
if s[end] in _ws:
end = _w(s, end + 1).end()
+ nextchar = s[end:end + 1]
except IndexError:
pass
+ if nextchar == ']':
+ raise JSONDecodeError("Illegal trailing comma before end of array", s, comma_idx)
return values, end
diff --git a/Lib/test/test_json/test_fail.py b/Lib/test/test_json/test_fail.py
index efc982e..d6bce60 100644
--- a/Lib/test/test_json/test_fail.py
+++ b/Lib/test/test_json/test_fail.py
@@ -143,11 +143,11 @@ class TestFail:
('{"spam":[}', 'Expecting value', 9),
('[42:', "Expecting ',' delimiter", 3),
('[42 "spam"', "Expecting ',' delimiter", 4),
- ('[42,]', 'Expecting value', 4),
+ ('[42,]', "Illegal trailing comma before end of array", 3),
('{"spam":[42}', "Expecting ',' delimiter", 11),
('["]', 'Unterminated string starting at', 1),
('["spam":', "Expecting ',' delimiter", 7),
- ('["spam",]', 'Expecting value', 8),
+ ('["spam",]', "Illegal trailing comma before end of array", 7),
('{:', 'Expecting property name enclosed in double quotes', 1),
('{,', 'Expecting property name enclosed in double quotes', 1),
('{42', 'Expecting property name enclosed in double quotes', 1),
@@ -159,7 +159,9 @@ class TestFail:
('[{"spam":]', 'Expecting value', 9),
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
('[{"spam":42]', "Expecting ',' delimiter", 11),
- ('{"spam":42,}', 'Expecting property name enclosed in double quotes', 11),
+ ('{"spam":42,}', "Illegal trailing comma before end of object", 10),
+ ('{"spam":42 , }', "Illegal trailing comma before end of object", 11),
+ ('[123 , ]', "Illegal trailing comma before end of array", 6),
]
for data, msg, idx in test_cases:
with self.assertRaises(self.JSONDecodeError) as cm:
diff --git a/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst b/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst
new file mode 100644
index 0000000..0faa67f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-16-23-56-42.gh-issue-113149.7LWgTS.rst
@@ -0,0 +1,2 @@
+Improve error message when a JSON array or object contains a trailing comma.
+Patch by Carson Radtke.
diff --git a/Modules/_json.c b/Modules/_json.c
index 0b1bfe3..24b292c 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -662,6 +662,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
PyObject *key = NULL;
int has_pairs_hook = (s->object_pairs_hook != Py_None);
Py_ssize_t next_idx;
+ Py_ssize_t comma_idx;
str = PyUnicode_DATA(pystr);
kind = PyUnicode_KIND(pystr);
@@ -741,10 +742,16 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
raise_errmsg("Expecting ',' delimiter", pystr, idx);
goto bail;
}
+ comma_idx = idx;
idx++;
/* skip whitespace after , delimiter */
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
+
+ if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}') {
+ raise_errmsg("Illegal trailing comma before end of object", pystr, comma_idx);
+ goto bail;
+ }
}
}
@@ -785,6 +792,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
PyObject *val = NULL;
PyObject *rval;
Py_ssize_t next_idx;
+ Py_ssize_t comma_idx;
rval = PyList_New(0);
if (rval == NULL)
@@ -822,10 +830,16 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
raise_errmsg("Expecting ',' delimiter", pystr, idx);
goto bail;
}
+ comma_idx = idx;
idx++;
/* skip whitespace after , */
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
+
+ if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']') {
+ raise_errmsg("Illegal trailing comma before end of array", pystr, comma_idx);
+ goto bail;
+ }
}
}