From d26686a7f87d63499f7296c0811fa0535637a93b Mon Sep 17 00:00:00 2001 From: Sergey Miryanov Date: Tue, 28 Oct 2025 14:28:32 +0500 Subject: [PATCH] GH-140590: Fix setstate for functools.partial C-module (GH-140671) Co-authored-by: Mikhail Efimov --- Lib/test/test_functools.py | 3 +++ .../Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst | 2 ++ Modules/_functoolsmodule.c | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index f7e09fd771ea..ce9e7f6d57dd 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -406,6 +406,7 @@ class TestPartial: def test_setstate_errors(self): f = self.partial(signature) + self.assertRaises(TypeError, f.__setstate__, (capture, (), {})) self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, {}, None)) self.assertRaises(TypeError, f.__setstate__, [capture, (), {}, None]) @@ -413,6 +414,8 @@ class TestPartial: self.assertRaises(TypeError, f.__setstate__, (capture, None, {}, None)) self.assertRaises(TypeError, f.__setstate__, (capture, [], {}, None)) self.assertRaises(TypeError, f.__setstate__, (capture, (), [], None)) + self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, ())) + self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, 'test')) def test_setstate_subclasses(self): f = self.partial(signature) diff --git a/Misc/NEWS.d/next/Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst b/Misc/NEWS.d/next/Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst new file mode 100644 index 000000000000..802183673cfa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst @@ -0,0 +1,2 @@ +Fix arguments checking for the :meth:`!functools.partial.__setstate__` that +may lead to internal state corruption and crash. Patch by Sergey Miryanov. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 44b1a302d49e..5773083ff68b 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -778,7 +778,8 @@ partial_setstate(PyObject *self, PyObject *state) if (!PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) || !PyCallable_Check(fn) || !PyTuple_Check(fnargs) || - (kw != Py_None && !PyDict_Check(kw))) + (kw != Py_None && !PyDict_Check(kw)) || + (dict != Py_None && !PyDict_Check(dict))) { PyErr_SetString(PyExc_TypeError, "invalid partial state"); return NULL; -- 2.47.3