From 679e9d36f78de3ac18abaaddbcf4f73fcef55b7e Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 2 Mar 2012 18:12:43 +0100 Subject: [PATCH] Issue #14172: Fix reference leak when marshalling a buffer-like object (other than a bytes object). --- Lib/test/test_marshal.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ Python/marshal.c | 8 ++++---- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py index cd100f9be44..9a250120ed8 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from test import support +import array import marshal import sys import unittest @@ -137,6 +138,27 @@ class ContainerTestCase(unittest.TestCase, HelperMixin): for constructor in (set, frozenset): self.helper(constructor(self.d.keys())) + +class BufferTestCase(unittest.TestCase, HelperMixin): + + def test_bytearray(self): + b = bytearray(b"abc") + self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + def test_memoryview(self): + b = memoryview(b"abc") + self.helper(b) + new = marshal.loads(marshal.dumps(b)) + self.assertEqual(type(new), bytes) + + def test_array(self): + a = array.array('B', b"abc") + new = marshal.loads(marshal.dumps(a)) + self.assertEqual(new, b"abc") + + class BugsTestCase(unittest.TestCase): def test_bug_5888452(self): # Simple-minded check for SF 588452: Debug build crashes @@ -243,6 +265,7 @@ def test_main(): CodeTestCase, ContainerTestCase, ExceptionTestCase, + BufferTestCase, BugsTestCase) if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS index c1385f3fad9..9c854a2aa54 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.2.3 release candidate 1? Core and Builtins ----------------- +- Issue #14172: Fix reference leak when marshalling a buffer-like object + (other than a bytes object). + - Issue #13521: dict.setdefault() now does only one lookup for the given key, making it "atomic" for many purposes. Patch by Filip GruszczyƄski. diff --git a/Python/marshal.c b/Python/marshal.c index 094f7323821..7b1af44f998 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -411,11 +411,12 @@ w_object(PyObject *v, WFILE *p) else if (PyObject_CheckBuffer(v)) { /* Write unknown buffer-style objects as a string */ char *s; - PyBufferProcs *pb = v->ob_type->tp_as_buffer; Py_buffer view; - if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) { + if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) { w_byte(TYPE_UNKNOWN, p); + p->depth--; p->error = WFERR_UNMARSHALLABLE; + return; } w_byte(TYPE_STRING, p); n = view.len; @@ -427,8 +428,7 @@ w_object(PyObject *v, WFILE *p) } w_long((long)n, p); w_string(s, (int)n, p); - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(v, &view); + PyBuffer_Release(&view); } else { w_byte(TYPE_UNKNOWN, p);