From 6d29352cfd76d569198dd2fd2eb02b2b0c5a8c44 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 11 Sep 2012 15:47:28 +0200 Subject: Issue #15895: my analysis was slightly off. The FILE pointer is only leaked when set_main_loader() fails for a pyc file with closeit=0. In the success case run_pyc_file() does its own cleanup of the fp. I've changed the code to use another FILE ptr for pyc files and moved the fclose() to PyRun_SimpleFileExFlags() to make it more obvious what's happening. --- Misc/NEWS | 3 ++- Python/pythonrun.c | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 068c4b1..0fe95da 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,8 @@ What's New in Python 3.3.1 Core and Builtins ----------------- -- Issue #15895: Fix FILE pointer leak in PyRun_SimpleFileExFlags() when +- Issue #15895: Fix FILE pointer leak in one error branch of + PyRun_SimpleFileExFlags() when filename points to a pyc/pyo file and closeit is false. - Issue #15900: Fix reference leak in PyUnicode_TranslateCharmap(). diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 7e9f654..b1ca125 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1385,7 +1385,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, close_own_fp = 0, ret; + int set_file_name = 0, ret; size_t len; m = PyImport_AddModule("__main__"); @@ -1411,15 +1411,15 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, len = strlen(filename); ext = filename + len - (len > 4 ? 4 : 0); if (maybe_pyc_file(fp, filename, ext, closeit)) { + FILE *pyc_fp; /* Try to run a pyc file. First, re-open in binary */ if (closeit) fclose(fp); - if ((fp = fopen(filename, "rb")) == NULL) { + if ((pyc_fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); ret = -1; goto done; } - close_own_fp = 1; /* Turn on optimization if a .pyo file is given */ if (strcmp(ext, ".pyo") == 0) Py_OptimizeFlag = 1; @@ -1427,9 +1427,11 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, if (set_main_loader(d, filename, "SourcelessFileLoader") < 0) { fprintf(stderr, "python: failed to set __main__.__loader__\n"); ret = -1; + fclose(pyc_fp); goto done; } - v = run_pyc_file(fp, filename, d, d, flags); + v = run_pyc_file(pyc_fp, filename, d, d, flags); + fclose(pyc_fp); } else { /* When running from stdin, leave __main__.__loader__ alone */ if (strcmp(filename, "") != 0 && @@ -1450,9 +1452,6 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, Py_DECREF(v); ret = 0; done: - if (close_own_fp) { - fclose(fp); - } if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); return ret; @@ -1999,7 +1998,6 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); v = PyMarshal_ReadLastObjectFromFile(fp); - fclose(fp); if (v == NULL || !PyCode_Check(v)) { Py_XDECREF(v); PyErr_SetString(PyExc_RuntimeError, -- cgit v0.12