From a5eb798e0c67eb240e96978ebf9e79d4125c23e6 Mon Sep 17 00:00:00 2001 From: Brij <97006829+bkap123@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:20:56 -0400 Subject: [PATCH 1/3] gh-146075: Prevent crash from malformed `str` subclass In `partial_vectorcall`, an error returned by `PyDict_Contains` was considered to be a truthy value. Now, the error is handled appropriately. --- Lib/test/test_functools.py | 12 ++++++++++++ Modules/_functoolsmodule.c | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index dda42cb33072c3..efa85b564f7cdf 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -565,7 +565,19 @@ def __repr__(self): g_partial = functools.partial(func, trigger, None, None, None, None, arg=None) self.assertEqual(repr(g_partial),"functools.partial(Function(old_function), EvilObject, None, None, None, None, arg=None)") + def test_str_subclass_error(self): + class BadStr(str): + def __eq__(self, other): + raise RuntimeError + def __hash__(self): + return str.__hash__(self) + + def f(**kwargs): + return kwargs + p = functools.partial(f, poison="") + with self.assertRaises(RuntimeError): + result = p(**{BadStr("poison"): "new_value"}) @unittest.skipUnless(c_functools, 'requires the C _functools module') class TestPartialC(TestPartial, unittest.TestCase): diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 723080ede1d9ae..576494e846ca0c 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -457,7 +457,11 @@ partial_vectorcall(PyObject *self, PyObject *const *args, for (Py_ssize_t i = 0; i < nkwds; ++i) { key = PyTuple_GET_ITEM(kwnames, i); val = args[nargs + i]; - if (PyDict_Contains(pto->kw, key)) { + int contains = PyDict_Contains(pto->kw, key); + if (contains < 0) { + goto error; + } + else if (contains == 1) { if (pto_kw_merged == NULL) { pto_kw_merged = PyDict_Copy(pto->kw); if (pto_kw_merged == NULL) { From 32c3e01a74069d3a722b55f3358e789fa11c8190 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:30:47 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst b/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst new file mode 100644 index 00000000000000..b62ec4f26fef41 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst @@ -0,0 +1 @@ +Errors when calling :func:`partial` with a malformed keyword will no longer crash the interpreter. From f1274c7b3acbdff3f65802053ac4aa79885de100 Mon Sep 17 00:00:00 2001 From: bkap123 <97006829+bkap123@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:01:54 -0400 Subject: [PATCH 3/3] Update 2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst --- .../next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst b/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst index b62ec4f26fef41..792ea3ad668690 100644 --- a/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst +++ b/Misc/NEWS.d/next/Library/2026-03-17-19-30-45.gh-issue-146075.85sCSh.rst @@ -1 +1 @@ -Errors when calling :func:`partial` with a malformed keyword will no longer crash the interpreter. +Errors when calling :func:`functools.partial` with a malformed keyword will no longer crash the interpreter.