]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-140590: Fix setstate for functools.partial C-module (GH-140671)
authorSergey Miryanov <sergey.miryanov@gmail.com>
Tue, 28 Oct 2025 09:28:32 +0000 (14:28 +0500)
committerGitHub <noreply@github.com>
Tue, 28 Oct 2025 09:28:32 +0000 (10:28 +0100)
Co-authored-by: Mikhail Efimov <efimov.mikhail@gmail.com>
Lib/test/test_functools.py
Misc/NEWS.d/next/Library/2025-10-27-18-29-42.gh-issue-140590.LT9HHn.rst [new file with mode: 0644]
Modules/_functoolsmodule.c

index f7e09fd771eaf2d9a6a4adf817f22adfec3ab1f8..ce9e7f6d57dd3c8fbc05fa05f66c3a804cacc92d 100644 (file)
@@ -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 (file)
index 0000000..8021836
--- /dev/null
@@ -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.
index 44b1a302d49ed212a76d1cd41622ed7ec614c2a6..5773083ff68b4614f9fdd309b43d399fa69a01b9 100644 (file)
@@ -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;