https://github.com/python/cpython/commit/ce8f5f98c6fc95a1704360d986a4d0281eeada79
commit: ce8f5f98c6fc95a1704360d986a4d0281eeada79
branch: main
author: Duane Griffin <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-14T11:25:46Z
summary:
gh-106287: Do not write objects after an unmarshalling error (GH-132715)
Writing out an object may involve a slot lookup, which is not safe to do with
an exception raised. In debug mode an assertion failure will occur if this
happens.
files:
A Misc/NEWS.d/next/Library/2025-04-19-17-34-11.gh-issue-132715.XXl47F.rst
M Lib/test/test_marshal.py
M Python/marshal.c
diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py
index 662bdfccc79125..28f24d0fc59cb0 100644
--- a/Lib/test/test_marshal.py
+++ b/Lib/test/test_marshal.py
@@ -413,6 +413,26 @@ def test_deterministic_sets(self):
_, dump_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1")
self.assertEqual(dump_0, dump_1)
+ def test_unmarshallable(self):
+ # Check no crash after encountering unmarshallable objects.
+ # See https://github.com/python/cpython/issues/106287.
+ fset = frozenset([int])
+ code = compile("a = 1", "<string>", "exec")
+ code = code.replace(co_consts=(1, fset, None))
+ cases = (('tuple', (fset,)),
+ ('list', [fset]),
+ ('set', fset),
+ ('dict key', {fset: 'x'}),
+ ('dict value', {'x': fset}),
+ ('dict key & value', {fset: fset}),
+ ('slice', slice(fset, fset)),
+ ('code', code))
+ for name, arg in cases:
+ with self.subTest(name, arg=arg):
+ with self.assertRaisesRegex(ValueError, "unmarshallable
object"):
+ marshal.dumps((arg, memoryview(b'')))
+
+
LARGE_SIZE = 2**31
pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
diff --git
a/Misc/NEWS.d/next/Library/2025-04-19-17-34-11.gh-issue-132715.XXl47F.rst
b/Misc/NEWS.d/next/Library/2025-04-19-17-34-11.gh-issue-132715.XXl47F.rst
new file mode 100644
index 00000000000000..191b4f16e0f400
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-19-17-34-11.gh-issue-132715.XXl47F.rst
@@ -0,0 +1 @@
+Skip writing objects during marshalling once a failure has occurred.
diff --git a/Python/marshal.c b/Python/marshal.c
index 69d6dd7cf0f802..190fcdc89afaa8 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -432,6 +432,10 @@ w_object(PyObject *v, WFILE *p)
{
char flag = '\0';
+ if (p->error != WFERR_OK) {
+ return;
+ }
+
p->depth++;
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
_______________________________________________
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]