[Python-checkins] cpython: type_call() now detect bugs in type new and init

victor.stinner python-checkins at python.org
Thu Sep 3 12:18:00 CEST 2015


https://hg.python.org/cpython/rev/40c659ec4d18
changeset:   97620:40c659ec4d18
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Thu Sep 03 12:16:49 2015 +0200
summary:
  type_call() now detect bugs in type new and init

* Call _Py_CheckFunctionResult() to check for bugs in type
  constructors (tp_new)
* Add assertions to ensure an exception was raised if tp_init failed
  or that no exception was raised if tp_init succeed

Refactor also the function to have less indentation.

files:
  Objects/typeobject.c |  46 ++++++++++++++++++-------------
  1 files changed, 27 insertions(+), 19 deletions(-)


diff --git a/Objects/typeobject.c b/Objects/typeobject.c
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -906,25 +906,33 @@
 #endif
 
     obj = type->tp_new(type, args, kwds);
-    if (obj != NULL) {
-        /* Ugly exception: when the call was type(something),
-           don't call tp_init on the result. */
-        if (type == &PyType_Type &&
-            PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
-            (kwds == NULL ||
-             (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
-            return obj;
-        /* If the returned object is not an instance of type,
-           it won't be initialized. */
-        if (!PyType_IsSubtype(Py_TYPE(obj), type))
-            return obj;
-        type = Py_TYPE(obj);
-        if (type->tp_init != NULL) {
-            int res = type->tp_init(obj, args, kwds);
-            if (res < 0) {
-                Py_DECREF(obj);
-                obj = NULL;
-            }
+    obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
+    if (obj == NULL)
+        return NULL;
+
+    /* Ugly exception: when the call was type(something),
+       don't call tp_init on the result. */
+    if (type == &PyType_Type &&
+        PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
+        (kwds == NULL ||
+         (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
+        return obj;
+
+    /* If the returned object is not an instance of type,
+       it won't be initialized. */
+    if (!PyType_IsSubtype(Py_TYPE(obj), type))
+        return obj;
+
+    type = Py_TYPE(obj);
+    if (type->tp_init != NULL) {
+        int res = type->tp_init(obj, args, kwds);
+        if (res < 0) {
+            assert(PyErr_Occurred());
+            Py_DECREF(obj);
+            obj = NULL;
+        }
+        else {
+            assert(!PyErr_Occurred());
         }
     }
     return obj;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list