From 9ed9329248dca1fb3e867027ea9f3ed194ca6d45 Mon Sep 17 00:00:00 2001 From: Andrew MacIntyre Date: Sun, 4 Apr 2004 07:08:20 +0000 Subject: [PATCH] Backport to 2.3: If a file is opened with an explicit buffer size >= 1, repeated close() calls would attempt to free() the buffer already free()ed on the first close(). [bug introduced with patch #788249] Making sure that the buffer is free()ed in file object deallocation is a belt-n-braces bit of insurance against a memory leak. --- Lib/test/test_file.py | 17 +++++++++++++++++ Misc/NEWS | 4 ++++ Objects/fileobject.c | 2 ++ 3 files changed, 23 insertions(+) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index 677dafc3f0df..62b0e669a4ea 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -109,6 +109,23 @@ f.close() if not f.closed: raise TestFailed, 'file.closed should be true' +# make sure that explicitly setting the buffer size doesn't cause +# misbehaviour especially with repeated close() calls +for s in (-1, 0, 1, 512): + try: + f = open(TESTFN, 'w', s) + f.write(str(s)) + f.close() + f.close() + f = open(TESTFN, 'r', s) + d = int(f.read()) + f.close() + f.close() + except IOError, msg: + raise TestFailed, 'error setting buffer size %d: %s' % (s, str(msg)) + if d != s: + raise TestFailed, 'readback failure using buffer size %d' + methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', 'xreadlines', '__iter__'] diff --git a/Misc/NEWS b/Misc/NEWS index bacc90991e50..7d6297c0ee6b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,6 +35,10 @@ Core and builtins to clear the error when attempts to get the __getstate__ attribute fail caused intermittent errors and odd behavior. +- fixed: if a file is opened with an explicit buffer size >= 1, repeated + close() calls would attempt to free() the buffer already free()ed on + the first call. + Library ------- diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 127abceae41e..11bbeb25978c 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -352,6 +352,7 @@ file_dealloc(PyFileObject *f) (*f->f_close)(f->f_fp); Py_END_ALLOW_THREADS } + PyMem_Free(f->f_setbuf); Py_XDECREF(f->f_name); Py_XDECREF(f->f_mode); Py_XDECREF(f->f_encoding); @@ -398,6 +399,7 @@ file_close(PyFileObject *f) f->f_fp = NULL; } PyMem_Free(f->f_setbuf); + f->f_setbuf = NULL; if (sts == EOF) return PyErr_SetFromErrno(PyExc_IOError); if (sts != 0) -- 2.47.3