Skip to content

Commit 75bbcd4

Browse files
committed
improve error when json has trailing comma
* add news entry * cjson impl * pyjson impl * update tests
1 parent f34e22c commit 75bbcd4

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

Lib/json/decoder.py

+7
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,13 @@ def JSONObject(s_and_end, strict, scan_once, object_hook, object_pairs_hook,
200200
break
201201
elif nextchar != ',':
202202
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
203+
comma_idx = end - 1
203204
end = _w(s, end).end()
204205
nextchar = s[end:end + 1]
205206
end += 1
206207
if nextchar != '"':
208+
if nextchar == '}':
209+
raise JSONDecodeError("Illegal trailing comma before end of object", s, comma_idx)
207210
raise JSONDecodeError(
208211
"Expecting property name enclosed in double quotes", s, end - 1)
209212
if object_pairs_hook is not None:
@@ -240,13 +243,17 @@ def JSONArray(s_and_end, scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
240243
break
241244
elif nextchar != ',':
242245
raise JSONDecodeError("Expecting ',' delimiter", s, end - 1)
246+
comma_idx = end - 1
243247
try:
244248
if s[end] in _ws:
245249
end += 1
246250
if s[end] in _ws:
247251
end = _w(s, end + 1).end()
252+
nextchar = s[end:end + 1]
248253
except IndexError:
249254
pass
255+
if nextchar == ']':
256+
raise JSONDecodeError("Illegal trailing comma before end of array", s, comma_idx)
250257

251258
return values, end
252259

Lib/test/test_json/test_fail.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,11 @@ def test_unexpected_data(self):
143143
('{"spam":[}', 'Expecting value', 9),
144144
('[42:', "Expecting ',' delimiter", 3),
145145
('[42 "spam"', "Expecting ',' delimiter", 4),
146-
('[42,]', 'Expecting value', 4),
146+
('[42,]', "Illegal trailing comma before end of array", 3),
147147
('{"spam":[42}', "Expecting ',' delimiter", 11),
148148
('["]', 'Unterminated string starting at', 1),
149149
('["spam":', "Expecting ',' delimiter", 7),
150-
('["spam",]', 'Expecting value', 8),
150+
('["spam",]', "Illegal trailing comma before end of array", 7),
151151
('{:', 'Expecting property name enclosed in double quotes', 1),
152152
('{,', 'Expecting property name enclosed in double quotes', 1),
153153
('{42', 'Expecting property name enclosed in double quotes', 1),
@@ -159,7 +159,7 @@ def test_unexpected_data(self):
159159
('[{"spam":]', 'Expecting value', 9),
160160
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
161161
('[{"spam":42]', "Expecting ',' delimiter", 11),
162-
('{"spam":42,}', 'Expecting property name enclosed in double quotes', 11),
162+
('{"spam":42,}', "Illegal trailing comma before end of object", 10),
163163
]
164164
for data, msg, idx in test_cases:
165165
with self.assertRaises(self.JSONDecodeError) as cm:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve error message when a JSON array or object contains a trailing comma.
2+
Patch by Carson Radtke.

Modules/_json.c

+16
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
662662
PyObject *key = NULL;
663663
int has_pairs_hook = (s->object_pairs_hook != Py_None);
664664
Py_ssize_t next_idx;
665+
Py_ssize_t comma_idx;
665666

666667
str = PyUnicode_DATA(pystr);
667668
kind = PyUnicode_KIND(pystr);
@@ -741,10 +742,17 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss
741742
raise_errmsg("Expecting ',' delimiter", pystr, idx);
742743
goto bail;
743744
}
745+
comma_idx = idx;
744746
idx++;
745747

746748
/* skip whitespace after , delimiter */
747749
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
750+
751+
if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}')
752+
{
753+
raise_errmsg("Illegal trailing comma before end of object", pystr, comma_idx);
754+
goto bail;
755+
}
748756
}
749757
}
750758

@@ -785,6 +793,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
785793
PyObject *val = NULL;
786794
PyObject *rval;
787795
Py_ssize_t next_idx;
796+
Py_ssize_t comma_idx;
788797

789798
rval = PyList_New(0);
790799
if (rval == NULL)
@@ -822,10 +831,17 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi
822831
raise_errmsg("Expecting ',' delimiter", pystr, idx);
823832
goto bail;
824833
}
834+
comma_idx = idx;
825835
idx++;
826836

827837
/* skip whitespace after , */
828838
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
839+
840+
if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']')
841+
{
842+
raise_errmsg("Illegal trailing comma before end of array", pystr, comma_idx);
843+
goto bail;
844+
}
829845
}
830846
}
831847

0 commit comments

Comments
 (0)