https://github.com/python/cpython/commit/ae5760527a57165573b305b52d2fa6d2528aab0c commit: ae5760527a57165573b305b52d2fa6d2528aab0c branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-01-14T11:52:20Z summary:
[3.14] gh-106287: Do not write objects after an unmarshalling error (GH-132715) (GH-143832) 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. (cherry picked from commit ce8f5f98c6fc95a1704360d986a4d0281eeada79) Co-authored-by: Duane Griffin <[email protected]> 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 5130edc91fa6fc..507e882e951a4e 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]
