# HG changeset patch
# User Bob Ippolito <bob@redivi.com>
# Date 1304783143 21600
#      Sat May 07 09:45:43 2011 -0600
# Node ID 245cf19b8f53fcb7187cfa9e304b2fd727dade68
# Parent  0b84b0936d8f57a13ffa43e97924859b207ec148
scan_once_str recursion check

diff --git a/CHANGES.txt b/CHANGES.txt
--- 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
--- a/simplejson/_speedups.c
+++ b/simplejson/_speedups.c
@@ -1628,68 +1628,92 @@
     */
     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;
     }
+    if (Py_EnterRecursiveCall(" while decoding a JSON document"))
+        return NULL;
     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);
+            break;
         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 */
-            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;
-                return Py_None;
+                rval = Py_None;
             }
+            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;
-                return Py_True;
+                rval = Py_True;
             }
+            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;
-                return Py_False;
+                rval = Py_False;
             }
+            else
+                fallthrough = 1;
             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);
             }
+            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') {
-                return _parse_constant(s, "Infinity", idx, next_idx_ptr);
+                rval = _parse_constant(s, "Infinity", idx, next_idx_ptr);
             }
+            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') {
-                return _parse_constant(s, "-Infinity", idx, next_idx_ptr);
+                rval = _parse_constant(s, "-Infinity", idx, next_idx_ptr);
             }
+            else
+                fallthrough = 1;
             break;
+        default:
+            fallthrough = 1;
     }
     /* 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 *