]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38913: Fix segfault in Py_BuildValue("(s#O)", ...) if entered with exception...
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 2 Mar 2020 06:42:39 +0000 (08:42 +0200)
committerGitHub <noreply@github.com>
Mon, 2 Mar 2020 06:42:39 +0000 (08:42 +0200)
Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Python/modsupport.c

diff --git a/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst
new file mode 100644 (file)
index 0000000..0e4d121
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed segfault in ``Py_BuildValue()`` called with a format containing "#"
+and undefined PY_SSIZE_T_CLEAN whwn an exception is set.
index eb31a0ef5c9335f6c417cdfd0a2a6fa600112be7..23a27e368c06678dc1fd630071e1433df70c0c61 100644 (file)
@@ -5258,6 +5258,9 @@ meth_fastcall_keywords(PyObject* self, PyObject* const* args,
     return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs);
 }
 
+
+static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *);
+
 static PyMethodDef TestMethods[] = {
     {"raise_exception",         raise_exception,                 METH_VARARGS},
     {"raise_memoryerror",       raise_memoryerror,               METH_NOARGS},
@@ -5322,6 +5325,7 @@ static PyMethodDef TestMethods[] = {
     {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
     {"PyBuffer_SizeFromFormat",  test_PyBuffer_SizeFromFormat, METH_VARARGS},
     {"test_buildvalue_N",       test_buildvalue_N,               METH_NOARGS},
+    {"test_buildvalue_issue38913", test_buildvalue_issue38913,   METH_NOARGS},
     {"get_args", get_args, METH_VARARGS},
     {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS},
     {"getargs_tuple",           getargs_tuple,                   METH_VARARGS},
@@ -6791,3 +6795,42 @@ PyInit__testcapi(void)
     PyState_AddModule(m, &_testcapimodule);
     return m;
 }
+
+
+/* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */
+
+#undef Py_BuildValue
+PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...);
+
+static PyObject *
+test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    PyObject *res;
+    const char str[] = "string";
+    const Py_UNICODE unicode[] = L"unicode";
+    PyErr_SetNone(PyExc_ZeroDivisionError);
+
+    res = Py_BuildValue("(s#O)", str, 1, Py_None);
+    assert(res == NULL);
+    if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
+        return NULL;
+    }
+    res = Py_BuildValue("(z#O)", str, 1, Py_None);
+    assert(res == NULL);
+    if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
+        return NULL;
+    }
+    res = Py_BuildValue("(y#O)", str, 1, Py_None);
+    assert(res == NULL);
+    if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
+        return NULL;
+    }
+    res = Py_BuildValue("(u#O)", unicode, 1, Py_None);
+    assert(res == NULL);
+    if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {
+        return NULL;
+    }
+
+    PyErr_Clear();
+    Py_RETURN_NONE;
+}
index 62558221077468a7e9a7768b5e05dac1c88c916d..7271af3ac5332f7b103ff39fca903e76ffadc479 100644 (file)
@@ -343,11 +343,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
                 if (flags & FLAG_SIZE_T)
                     n = va_arg(*p_va, Py_ssize_t);
                 else {
+                    n = va_arg(*p_va, int);
                     if (PyErr_WarnEx(PyExc_DeprecationWarning,
                                 "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
                         return NULL;
                     }
-                    n = va_arg(*p_va, int);
                 }
             }
             else
@@ -396,11 +396,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
                 if (flags & FLAG_SIZE_T)
                     n = va_arg(*p_va, Py_ssize_t);
                 else {
+                    n = va_arg(*p_va, int);
                     if (PyErr_WarnEx(PyExc_DeprecationWarning,
                                 "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
                         return NULL;
                     }
-                    n = va_arg(*p_va, int);
                 }
             }
             else
@@ -434,11 +434,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
                 if (flags & FLAG_SIZE_T)
                     n = va_arg(*p_va, Py_ssize_t);
                 else {
+                    n = va_arg(*p_va, int);
                     if (PyErr_WarnEx(PyExc_DeprecationWarning,
                                 "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
                         return NULL;
                     }
-                    n = va_arg(*p_va, int);
                 }
             }
             else