summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-03-02 06:42:39 (GMT)
committerGitHub <noreply@github.com>2020-03-02 06:42:39 (GMT)
commit28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb (patch)
tree83383bd4da7d3e8353faae7a29d7658691f299ca
parent2565edec2c974b2acca03b4cc5025e83f903ddd7 (diff)
downloadcpython-28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb.zip
cpython-28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb.tar.gz
cpython-28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb.tar.bz2
bpo-38913: Fix segfault in Py_BuildValue("(s#O)", ...) if entered with exception raised. (GH-18656)
-rw-r--r--Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst2
-rw-r--r--Modules/_testcapimodule.c43
-rw-r--r--Python/modsupport.c6
3 files changed, 48 insertions, 3 deletions
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
index 0000000..0e4d121
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst
@@ -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.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index eb31a0e..23a27e3 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -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;
+}
diff --git a/Python/modsupport.c b/Python/modsupport.c
index 6255822..7271af3 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -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