diff -r b21288c1ec68 Lib/json/decoder.py --- a/Lib/json/decoder.py Thu Oct 04 12:45:10 2012 -0400 +++ b/Lib/json/decoder.py Thu Oct 04 22:23:04 2012 +0300 @@ -196,8 +196,8 @@ try: value, end = scan_once(s, end) - except StopIteration: - raise ValueError(errmsg("Expecting object", s, end)) + except StopIteration as err: + raise ValueError(errmsg("Expecting value", s, err.value)) from None pairs_append((key, value)) try: nextchar = s[end] @@ -240,8 +240,8 @@ while True: try: value, end = scan_once(s, end) - except StopIteration: - raise ValueError(errmsg("Expecting object", s, end)) + except StopIteration as err: + raise ValueError(errmsg("Expecting value", s, err.value)) from None _append(value) nextchar = s[end:end + 1] if nextchar in _ws: @@ -366,6 +366,6 @@ """ try: obj, end = self.scan_once(s, idx) - except StopIteration: - raise ValueError("No JSON object could be decoded") + except StopIteration as err: + raise ValueError(errmsg("Expecting value", s, err.value)) from None return obj, end diff -r b21288c1ec68 Lib/json/scanner.py --- a/Lib/json/scanner.py Thu Oct 04 12:45:10 2012 -0400 +++ b/Lib/json/scanner.py Thu Oct 04 22:23:04 2012 +0300 @@ -29,7 +29,7 @@ try: nextchar = string[idx] except IndexError: - raise StopIteration + raise StopIteration(idx) if nextchar == '"': return parse_string(string, idx + 1, strict) @@ -60,7 +60,7 @@ elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': return parse_constant('-Infinity'), idx + 9 else: - raise StopIteration + raise StopIteration(idx) def scan_once(string, idx): try: diff -r b21288c1ec68 Modules/_json.c --- a/Modules/_json.c Thu Oct 04 12:45:10 2012 -0400 +++ b/Modules/_json.c Thu Oct 04 22:23:04 2012 +0300 @@ -273,6 +273,16 @@ } } +static void +raise_stop_iteration(Py_ssize_t idx) +{ + PyObject *value = PyLong_FromSsize_t(idx); + if (value != NULL) { + PyErr_SetObject(PyExc_StopIteration, value); + Py_DECREF(value); + } +} + static PyObject * _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) { /* return (rval, idx) tuple, stealing reference to rval */ @@ -342,7 +352,7 @@ buf = PyUnicode_DATA(pystr); kind = PyUnicode_KIND(pystr); - if (end < 0 || len <= end) { + if (end < 0 || len < end) { PyErr_SetString(PyExc_ValueError, "end is out of bounds"); goto bail; } @@ -640,12 +650,12 @@ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind,str, idx))) idx++; /* only loop if the object is non-empty */ - if (idx <= end_idx && PyUnicode_READ(kind, str, idx) != '}') { - while (idx <= end_idx) { + if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '}') { + while (1) { PyObject *memokey; /* read key */ - if (PyUnicode_READ(kind, str, idx) != '"') { + if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '"') { raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx); goto bail; } @@ -702,11 +712,9 @@ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; /* bail if the object is closed or we didn't get the , delimiter */ - if (idx > end_idx) break; - if (PyUnicode_READ(kind, str, idx) == '}') { + if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == '}') break; - } - else if (PyUnicode_READ(kind, str, idx) != ',') { + if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ',') { raise_errmsg("Expecting ',' delimiter", pystr, idx); goto bail; } @@ -717,12 +725,6 @@ } } - /* verify that idx < end_idx, str[idx] should be '}' */ - if (idx > end_idx || PyUnicode_READ(kind, str, idx) != '}') { - raise_errmsg("Expecting object", pystr, end_idx); - goto bail; - } - *next_idx_ptr = idx + 1; if (has_pairs_hook) { @@ -774,8 +776,8 @@ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; /* only loop if the array is non-empty */ - if (idx <= end_idx && PyUnicode_READ(kind, str, idx) != ']') { - while (idx <= end_idx) { + if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ']') { + while (1) { /* read any JSON term */ val = scan_once_unicode(s, pystr, idx, &next_idx); @@ -792,11 +794,9 @@ while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; /* bail if the array is closed or we didn't get the , delimiter */ - if (idx > end_idx) break; - if (PyUnicode_READ(kind, str, idx) == ']') { + if (idx <= end_idx && PyUnicode_READ(kind, str, idx) == ']') break; - } - else if (PyUnicode_READ(kind, str, idx) != ',') { + if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ',') { raise_errmsg("Expecting ',' delimiter", pystr, idx); goto bail; } @@ -809,7 +809,7 @@ /* verify that idx < end_idx, PyUnicode_READ(kind, str, idx) should be ']' */ if (idx > end_idx || PyUnicode_READ(kind, str, idx) != ']') { - raise_errmsg("Expecting object", pystr, end_idx); + raise_errmsg("Expecting value2", pystr, end_idx); goto bail; } *next_idx_ptr = idx + 1; @@ -877,7 +877,7 @@ if (PyUnicode_READ(kind, str, idx) == '-') { idx++; if (idx > end_idx) { - PyErr_SetNone(PyExc_StopIteration); + raise_stop_iteration(start); return NULL; } } @@ -893,7 +893,7 @@ } /* no integer digits, error */ else { - PyErr_SetNone(PyExc_StopIteration); + raise_stop_iteration(start); return NULL; } @@ -986,7 +986,7 @@ length = PyUnicode_GET_LENGTH(pystr); if (idx >= length) { - PyErr_SetNone(PyExc_StopIteration); + raise_stop_iteration(idx); return NULL; }