Skip to content

Commit 8c6d876

Browse files
[3.13] gh-106287: Do not write objects after an unmarshalling error (GH-132715) (GH-143833)
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 ce8f5f9) Co-authored-by: Duane Griffin <duaneg@dghda.com>
1 parent 5f7a49a commit 8c6d876

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

Lib/test/test_marshal.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,26 @@ def test_deterministic_sets(self):
406406
_, dump_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1")
407407
self.assertEqual(dump_0, dump_1)
408408

409+
def test_unmarshallable(self):
410+
# Check no crash after encountering unmarshallable objects.
411+
# See https://github.com/python/cpython/issues/106287.
412+
fset = frozenset([int])
413+
code = compile("a = 1", "<string>", "exec")
414+
code = code.replace(co_consts=(1, fset, None))
415+
cases = (('tuple', (fset,)),
416+
('list', [fset]),
417+
('set', fset),
418+
('dict key', {fset: 'x'}),
419+
('dict value', {'x': fset}),
420+
('dict key & value', {fset: fset}),
421+
('slice', slice(fset, fset)),
422+
('code', code))
423+
for name, arg in cases:
424+
with self.subTest(name, arg=arg):
425+
with self.assertRaisesRegex(ValueError, "unmarshallable object"):
426+
marshal.dumps((arg, memoryview(b'')))
427+
428+
409429
LARGE_SIZE = 2**31
410430
pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4
411431

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Skip writing objects during marshalling once a failure has occurred.

Python/marshal.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ w_object(PyObject *v, WFILE *p)
362362
{
363363
char flag = '\0';
364364

365+
if (p->error != WFERR_OK) {
366+
return;
367+
}
368+
365369
p->depth++;
366370

367371
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {

0 commit comments

Comments
 (0)