mirror of https://github.com/python/cpython
bpo-36379: __ipow__ must be a ternaryfunc, not a binaryfunc (GH-13546)
If a type's __ipow__ method was implemented in C, attempting to use the *modulo* parameter would cause crashes. https://bugs.python.org/issue36379
This commit is contained in:
parent
c7f7069e77
commit
c7f803b08e
|
@ -184,6 +184,13 @@ class CAPITest(unittest.TestCase):
|
||||||
o @= m1
|
o @= m1
|
||||||
self.assertEqual(o, ("matmul", 42, m1))
|
self.assertEqual(o, ("matmul", 42, m1))
|
||||||
|
|
||||||
|
def test_c_type_with_ipow(self):
|
||||||
|
# When the __ipow__ method of a type was implemented in C, using the
|
||||||
|
# modulo param would cause segfaults.
|
||||||
|
o = _testcapi.ipowType()
|
||||||
|
self.assertEqual(o.__ipow__(1), (1, None))
|
||||||
|
self.assertEqual(o.__ipow__(2, 2), (2, 2))
|
||||||
|
|
||||||
def test_return_null_without_error(self):
|
def test_return_null_without_error(self):
|
||||||
# Issue #23571: A function must not return NULL without setting an
|
# Issue #23571: A function must not return NULL without setting an
|
||||||
# error
|
# error
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix crashes when attempting to use the *modulo* parameter when ``__ipow__``
|
||||||
|
is implemented in C.
|
|
@ -5522,6 +5522,27 @@ static PyTypeObject matmulType = {
|
||||||
PyObject_Del, /* tp_free */
|
PyObject_Del, /* tp_free */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
} ipowObject;
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
ipowType_ipow(PyObject *self, PyObject *other, PyObject *mod)
|
||||||
|
{
|
||||||
|
return Py_BuildValue("OO", other, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyNumberMethods ipowType_as_number = {
|
||||||
|
.nb_inplace_power = ipowType_ipow
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject ipowType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
.tp_name = "ipowType",
|
||||||
|
.tp_basicsize = sizeof(ipowObject),
|
||||||
|
.tp_as_number = &ipowType_as_number,
|
||||||
|
.tp_new = PyType_GenericNew
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
@ -5947,6 +5968,11 @@ PyInit__testcapi(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
Py_INCREF(&matmulType);
|
Py_INCREF(&matmulType);
|
||||||
PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType);
|
PyModule_AddObject(m, "matmulType", (PyObject *)&matmulType);
|
||||||
|
if (PyType_Ready(&ipowType) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_INCREF(&ipowType);
|
||||||
|
PyModule_AddObject(m, "ipowType", (PyObject *)&ipowType);
|
||||||
|
|
||||||
if (PyType_Ready(&awaitType) < 0)
|
if (PyType_Ready(&awaitType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -7016,7 +7016,7 @@ static slotdef slotdefs[] = {
|
||||||
IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
|
IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
|
||||||
wrap_binaryfunc, "%="),
|
wrap_binaryfunc, "%="),
|
||||||
IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
|
IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
|
||||||
wrap_binaryfunc, "**="),
|
wrap_ternaryfunc, "**="),
|
||||||
IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
|
IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
|
||||||
wrap_binaryfunc, "<<="),
|
wrap_binaryfunc, "<<="),
|
||||||
IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,
|
IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,
|
||||||
|
|
Loading…
Reference in New Issue