summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_capi.py7
-rw-r--r--Misc/NEWS.d/next/C API/2019-05-24-07-11-08.bpo-36379.8zgoKe.rst2
-rw-r--r--Modules/_testcapimodule.c26
-rw-r--r--Objects/typeobject.c2
4 files changed, 36 insertions, 1 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 795aa78..4dd78bb 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -184,6 +184,13 @@ class CAPITest(unittest.TestCase):
o @= 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):
# Issue #23571: A function must not return NULL without setting an
# error
diff --git a/Misc/NEWS.d/next/C API/2019-05-24-07-11-08.bpo-36379.8zgoKe.rst b/Misc/NEWS.d/next/C API/2019-05-24-07-11-08.bpo-36379.8zgoKe.rst
new file mode 100644
index 0000000..6a699b2
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2019-05-24-07-11-08.bpo-36379.8zgoKe.rst
@@ -0,0 +1,2 @@
+Fix crashes when attempting to use the *modulo* parameter when ``__ipow__``
+is implemented in C.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index ca6e87b..b42f41c 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -5522,6 +5522,27 @@ static PyTypeObject matmulType = {
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 {
PyObject_HEAD
@@ -5947,6 +5968,11 @@ PyInit__testcapi(void)
return NULL;
Py_INCREF(&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)
return NULL;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 64c2cea..b6d925c 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -7016,7 +7016,7 @@ static slotdef slotdefs[] = {
IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
wrap_binaryfunc, "%="),
IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
- wrap_binaryfunc, "**="),
+ wrap_ternaryfunc, "**="),
IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
wrap_binaryfunc, "<<="),
IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,