diff --git a/CHANGES.txt b/CHANGES.txt index 0b84b0936d8f57a13ffa43e97924859b207ec148_Q0hBTkdFUy50eHQ=..245cf19b8f53fcb7187cfa9e304b2fd727dade68_Q0hBTkdFUy50eHQ= 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,7 @@ Version 2.1.6 released 2011-XX-XX +* Prevent segfaults with deeply nested JSON documents + https://github.com/simplejson/simplejson/issues/11 * Fix compatibility with Python 2.5 https://github.com/simplejson/simplejson/issues/5 diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 0b84b0936d8f57a13ffa43e97924859b207ec148_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw==..245cf19b8f53fcb7187cfa9e304b2fd727dade68_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw== 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -1628,7 +1628,9 @@ */ char *str = PyString_AS_STRING(pystr); Py_ssize_t length = PyString_GET_SIZE(pystr); + PyObject *rval = NULL; + int fallthrough = 0; if (idx >= length) { PyErr_SetNone(PyExc_StopIteration); return NULL; } @@ -1631,7 +1633,9 @@ if (idx >= length) { PyErr_SetNone(PyExc_StopIteration); return NULL; } + if (Py_EnterRecursiveCall(" while decoding a JSON document")) + return NULL; switch (str[idx]) { case '"': /* string */ @@ -1635,7 +1639,7 @@ switch (str[idx]) { case '"': /* string */ - return scanstring_str(pystr, idx + 1, + rval = scanstring_str(pystr, idx + 1, PyString_AS_STRING(s->encoding), PyObject_IsTrue(s->strict), next_idx_ptr); @@ -1639,5 +1643,6 @@ PyString_AS_STRING(s->encoding), PyObject_IsTrue(s->strict), next_idx_ptr); + break; case '{': /* object */ @@ -1642,5 +1647,6 @@ case '{': /* object */ - return _parse_object_str(s, pystr, idx + 1, next_idx_ptr); + rval = _parse_object_str(s, pystr, idx + 1, next_idx_ptr); + break; case '[': /* array */ @@ -1645,8 +1651,9 @@ case '[': /* array */ - return _parse_array_str(s, pystr, idx + 1, next_idx_ptr); + rval = _parse_array_str(s, pystr, idx + 1, next_idx_ptr); + break; case 'n': /* null */ if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { Py_INCREF(Py_None); *next_idx_ptr = idx + 4; @@ -1648,7 +1655,7 @@ case 'n': /* null */ if ((idx + 3 < length) && str[idx + 1] == 'u' && str[idx + 2] == 'l' && str[idx + 3] == 'l') { Py_INCREF(Py_None); *next_idx_ptr = idx + 4; - return Py_None; + rval = Py_None; } @@ -1654,7 +1661,9 @@ } + else + fallthrough = 1; break; case 't': /* true */ if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') { Py_INCREF(Py_True); *next_idx_ptr = idx + 4; @@ -1655,8 +1664,8 @@ break; case 't': /* true */ if ((idx + 3 < length) && str[idx + 1] == 'r' && str[idx + 2] == 'u' && str[idx + 3] == 'e') { Py_INCREF(Py_True); *next_idx_ptr = idx + 4; - return Py_True; + rval = Py_True; } @@ -1662,7 +1671,9 @@ } + else + fallthrough = 1; break; case 'f': /* false */ if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') { Py_INCREF(Py_False); *next_idx_ptr = idx + 5; @@ -1663,8 +1674,8 @@ break; case 'f': /* false */ if ((idx + 4 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'l' && str[idx + 3] == 's' && str[idx + 4] == 'e') { Py_INCREF(Py_False); *next_idx_ptr = idx + 5; - return Py_False; + rval = Py_False; } @@ -1670,5 +1681,7 @@ } + else + fallthrough = 1; break; case 'N': /* NaN */ if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') { @@ -1671,6 +1684,6 @@ break; case 'N': /* NaN */ if ((idx + 2 < length) && str[idx + 1] == 'a' && str[idx + 2] == 'N') { - return _parse_constant(s, "NaN", idx, next_idx_ptr); + rval = _parse_constant(s, "NaN", idx, next_idx_ptr); } @@ -1676,5 +1689,7 @@ } + else + fallthrough = 1; break; case 'I': /* Infinity */ if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') { @@ -1677,6 +1692,6 @@ break; case 'I': /* Infinity */ if ((idx + 7 < length) && str[idx + 1] == 'n' && str[idx + 2] == 'f' && str[idx + 3] == 'i' && str[idx + 4] == 'n' && str[idx + 5] == 'i' && str[idx + 6] == 't' && str[idx + 7] == 'y') { - return _parse_constant(s, "Infinity", idx, next_idx_ptr); + rval = _parse_constant(s, "Infinity", idx, next_idx_ptr); } @@ -1682,5 +1697,7 @@ } + else + fallthrough = 1; break; case '-': /* -Infinity */ if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') { @@ -1683,6 +1700,6 @@ break; case '-': /* -Infinity */ if ((idx + 8 < length) && str[idx + 1] == 'I' && str[idx + 2] == 'n' && str[idx + 3] == 'f' && str[idx + 4] == 'i' && str[idx + 5] == 'n' && str[idx + 6] == 'i' && str[idx + 7] == 't' && str[idx + 8] == 'y') { - return _parse_constant(s, "-Infinity", idx, next_idx_ptr); + rval = _parse_constant(s, "-Infinity", idx, next_idx_ptr); } @@ -1688,2 +1705,4 @@ } + else + fallthrough = 1; break; @@ -1689,3 +1708,5 @@ break; + default: + fallthrough = 1; } /* Didn't find a string, object, array, or named constant. Look for a number. */ @@ -1690,6 +1711,9 @@ } /* Didn't find a string, object, array, or named constant. Look for a number. */ - return _match_number_str(s, pystr, idx, next_idx_ptr); + if (fallthrough) + rval = _match_number_str(s, pystr, idx, next_idx_ptr); + Py_LeaveRecursiveCall(); + return rval; } static PyObject *