summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-12-07 09:27:55 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-12-07 09:27:55 (GMT)
commit1b58d8aafa5c4705deeb898027b33c4be7bc71e1 (patch)
tree6de0a97a68737cff11b88c40512ebf0bd19e5f83 /Objects
parent4fc7942118f017c214534d29b18f2f844e68c8cf (diff)
parent0c78634d785361dcde0c2c138e8bf5f9bb744d3d (diff)
downloadcpython-1b58d8aafa5c4705deeb898027b33c4be7bc71e1.zip
cpython-1b58d8aafa5c4705deeb898027b33c4be7bc71e1.tar.gz
cpython-1b58d8aafa5c4705deeb898027b33c4be7bc71e1.tar.bz2
Issue #5322: Fixed setting __new__ to a PyCFunction inside Python code.
Original patch by Andreas Stührk.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 1758de2..c7f49b7 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6878,7 +6878,34 @@ update_one_slot(PyTypeObject *type, slotdef *p)
sanity checks and constructing a new argument
list. Cut all that nonsense short -- this speeds
up instance creation tremendously. */
- specific = (void *)type->tp_new;
+ PyObject *self = PyCFunction_GET_SELF(descr);
+ if (!self || !PyType_Check(self)) {
+ /* This should never happen because
+ tp_new_wrapper expects a type for self.
+ Use slot_tp_new which will call
+ tp_new_wrapper which will raise an
+ exception. */
+ specific = (void *)slot_tp_new;
+ }
+ else {
+ PyTypeObject *staticbase;
+ specific = ((PyTypeObject *)self)->tp_new;
+ /* Check that the user does not do anything
+ silly and unsafe like object.__new__(dict).
+ To do this, we check that the most derived
+ base that's not a heap type is this type. */
+ staticbase = type->tp_base;
+ while (staticbase &&
+ (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE))
+ staticbase = staticbase->tp_base;
+ if (staticbase &&
+ staticbase->tp_new != specific)
+ /* Seems to be unsafe, better use
+ slot_tp_new which will call
+ tp_new_wrapper which will raise an
+ exception if it is unsafe. */
+ specific = (void *)slot_tp_new;
+ }
/* XXX I'm not 100% sure that there isn't a hole
in this reasoning that requires additional
sanity checks. I'll buy the first person to