psss / rpms / python3

Forked from rpms/python3 5 years ago
Clone
ffd8034
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
ffd8034
index 847b50140a6..570dc3ed6fe 100644
ffd8034
--- a/Doc/whatsnew/3.6.rst
ffd8034
+++ b/Doc/whatsnew/3.6.rst
ffd8034
@@ -1852,10 +1852,10 @@ Build and C API Changes
ffd8034
 * The :c:func:`PyUnicode_FSConverter` and :c:func:`PyUnicode_FSDecoder`
ffd8034
   functions will now accept :term:`path-like objects <path-like object>`.
ffd8034
 
ffd8034
-* The ``PyExc_RecursionErrorInst`` singleton that was part of the public API
ffd8034
-  has been removed as its members being never cleared may cause a segfault
ffd8034
-  during finalization of the interpreter. Contributed by Xavier de Gaye in
ffd8034
-  :issue:`22898` and :issue:`30697`.
ffd8034
+* The ``PyExc_RecursionErrorInst`` singleton is not used anymore as its members
ffd8034
+  being never cleared may cause a segfault during finalization of the
ffd8034
+  interpreter. Contributed by Xavier de Gaye in :issue:`22898` and
ffd8034
+  :issue:`30697`.
ffd8034
 
ffd8034
 
ffd8034
 Other Improvements
ffd8034
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
ffd8034
index c28c1373f82..8c1dbc5047b 100644
ffd8034
--- a/Include/pyerrors.h
ffd8034
+++ b/Include/pyerrors.h
ffd8034
@@ -219,6 +219,8 @@ PyAPI_DATA(PyObject *) PyExc_IOError;
ffd8034
 PyAPI_DATA(PyObject *) PyExc_WindowsError;
ffd8034
 #endif
ffd8034
 
ffd8034
+PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst;
ffd8034
+
ffd8034
 /* Predefined warning categories */
ffd8034
 PyAPI_DATA(PyObject *) PyExc_Warning;
ffd8034
 PyAPI_DATA(PyObject *) PyExc_UserWarning;
ffd8034
diff --git a/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst
ffd8034
new file mode 100644
ffd8034
index 00000000000..28f74ad4f30
ffd8034
--- /dev/null
ffd8034
+++ b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst	
ffd8034
@@ -0,0 +1 @@
ffd8034
+Restore PyExc_RecursionErrorInst in 3.6
ffd8034
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
ffd8034
index df4899372a5..271e293e325 100644
ffd8034
--- a/Objects/exceptions.c
ffd8034
+++ b/Objects/exceptions.c
ffd8034
@@ -2430,6 +2430,12 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
ffd8034
 
ffd8034
 
ffd8034
 
ffd8034
+/* Pre-computed RecursionError instance for when recursion depth is reached.
ffd8034
+   Meant to be used when normalizing the exception for exceeding the recursion
ffd8034
+   depth will cause its own infinite recursion.
ffd8034
+*/
ffd8034
+PyObject *PyExc_RecursionErrorInst = NULL;
ffd8034
+
ffd8034
 #define PRE_INIT(TYPE) \
ffd8034
     if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
ffd8034
         if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \
ffd8034
@@ -2691,11 +2697,37 @@ _PyExc_Init(PyObject *bltinmod)
ffd8034
     ADD_ERRNO(TimeoutError, ETIMEDOUT);
ffd8034
 
ffd8034
     preallocate_memerrors();
ffd8034
+
ffd8034
+    if (!PyExc_RecursionErrorInst) {
ffd8034
+        PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RecursionError, NULL, NULL);
ffd8034
+        if (!PyExc_RecursionErrorInst)
ffd8034
+            Py_FatalError("Cannot pre-allocate RecursionError instance for "
ffd8034
+                            "recursion errors");
ffd8034
+        else {
ffd8034
+            PyBaseExceptionObject *err_inst =
ffd8034
+                (PyBaseExceptionObject *)PyExc_RecursionErrorInst;
ffd8034
+            PyObject *args_tuple;
ffd8034
+            PyObject *exc_message;
ffd8034
+            exc_message = PyUnicode_FromString("maximum recursion depth exceeded");
ffd8034
+            if (!exc_message)
ffd8034
+                Py_FatalError("cannot allocate argument for RecursionError "
ffd8034
+                                "pre-allocation");
ffd8034
+            args_tuple = PyTuple_Pack(1, exc_message);
ffd8034
+            if (!args_tuple)
ffd8034
+                Py_FatalError("cannot allocate tuple for RecursionError "
ffd8034
+                                "pre-allocation");
ffd8034
+            Py_DECREF(exc_message);
ffd8034
+            if (BaseException_init(err_inst, args_tuple, NULL))
ffd8034
+                Py_FatalError("init of pre-allocated RecursionError failed");
ffd8034
+            Py_DECREF(args_tuple);
ffd8034
+        }
ffd8034
+    }
ffd8034
 }
ffd8034
 
ffd8034
 void
ffd8034
 _PyExc_Fini(void)
ffd8034
 {
ffd8034
+    Py_CLEAR(PyExc_RecursionErrorInst);
ffd8034
     free_preallocated_memerrors();
ffd8034
     Py_CLEAR(errnomap);
ffd8034
 }
ffd8034
diff --git a/PC/python3.def b/PC/python3.def
ffd8034
index 4fc4a6814ee..ff70718fc37 100644
ffd8034
--- a/PC/python3.def
ffd8034
+++ b/PC/python3.def
ffd8034
@@ -224,6 +224,7 @@ EXPORTS
ffd8034
   PyExc_PermissionError=python36.PyExc_PermissionError DATA
ffd8034
   PyExc_ProcessLookupError=python36.PyExc_ProcessLookupError DATA
ffd8034
   PyExc_RecursionError=python36.PyExc_RecursionError DATA
ffd8034
+  PyExc_RecursionErrorInst=python36.PyExc_RecursionErrorInst DATA
ffd8034
   PyExc_ReferenceError=python36.PyExc_ReferenceError DATA
ffd8034
   PyExc_ResourceWarning=python36.PyExc_ResourceWarning DATA
ffd8034
   PyExc_RuntimeError=python36.PyExc_RuntimeError DATA