https://github.com/python/cpython/commit/cd2e47135cca67ccaa4e039adf279a85d8fbc1d1
commit: cd2e47135cca67ccaa4e039adf279a85d8fbc1d1
branch: 3.13
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2026-03-14T11:00:56Z
summary:
[3.13] gh-143636: fix a crash when calling ``__replace__`` on invalid
`SimpleNamespace` instances (GH-143655) (#145940)
[3.13] gh-143636: fix a crash when calling ``__replace__`` on invalid
`SimpleNamespace` instances (GH-143655)
(cherry picked from commit 97968564b61965f2a65a9be8af731cee6913eb7a)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst
M Lib/test/test_types.py
M Objects/namespaceobject.c
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index d7c229151b3ab4..f7c701e5f3c732 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -2037,6 +2037,21 @@ class Spam(types.SimpleNamespace):
self.assertIs(type(spam2), Spam)
self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9})
+ def test_replace_invalid_subtype(self):
+ # See https://github.com/python/cpython/issues/143636.
+ class MyNS(types.SimpleNamespace):
+ def __new__(cls, *args, **kwargs):
+ if created:
+ return 12345
+ return super().__new__(cls)
+
+ created = False
+ ns = MyNS()
+ created = True
+ err = (r"^expect types\.SimpleNamespace type, "
+ r"but .+\.MyNS\(\) returned 'int' object")
+ self.assertRaisesRegex(TypeError, err, copy.replace, ns)
+
def test_fake_namespace_compare(self):
# Issue #24257: Incorrect use of PyObject_IsInstance() caused
# SystemError.
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst
new file mode 100644
index 00000000000000..4d5249ffe3a206
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-10-12-59-58.gh-issue-143636.dzr26e.rst
@@ -0,0 +1,2 @@
+Fix a crash when calling :class:`SimpleNamespace.__replace__()
+<types.SimpleNamespace>` on non-namespace instances. Patch by Bénédikt Tran.
diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c
index 7eeac11b553810..4b1d625fc78232 100644
--- a/Objects/namespaceobject.c
+++ b/Objects/namespaceobject.c
@@ -12,6 +12,9 @@ typedef struct {
PyObject *ns_dict;
} _PyNamespaceObject;
+#define _PyNamespace_CAST(op) _Py_CAST(_PyNamespaceObject*, (op))
+#define _PyNamespace_Check(op) PyObject_TypeCheck((op), &_PyNamespace_Type)
+
static PyMemberDef namespace_members[] = {
{"__dict__", _Py_T_OBJECT, offsetof(_PyNamespaceObject, ns_dict),
Py_READONLY},
@@ -223,6 +226,14 @@ namespace_replace(PyObject *self, PyObject *args, PyObject
*kwargs)
if (!result) {
return NULL;
}
+ if (!_PyNamespace_Check(result)) {
+ PyErr_Format(PyExc_TypeError,
+ "expect %N type, but %T() returned '%T' object",
+ &_PyNamespace_Type, self, result);
+ Py_DECREF(result);
+ return NULL;
+ }
+
if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict,
((_PyNamespaceObject*)self)->ns_dict) < 0)
{
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]