diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 05e29d42e6a..d12caeb0e1c 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -2,9 +2,12 @@ # All tests are executed with environment variables ignored # See test_cmd_line_script.py for testing of script execution -import test.test_support, unittest +import test.test_support import sys -from test.script_helper import spawn_python, kill_python, python_exit_code +import unittest +from test.script_helper import ( + assert_python_ok, spawn_python, kill_python, python_exit_code +) class CmdLineTest(unittest.TestCase): @@ -101,6 +104,18 @@ class CmdLineTest(unittest.TestCase): data = self.start_python('-R', '-c', code) self.assertTrue('hash_randomization=1' in data) + def test_del___main__(self): + # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a + # borrowed reference to the dict of __main__ module and later modify + # the dict whereas the module was destroyed + filename = test.test_support.TESTFN + self.addCleanup(test.test_support.unlink, filename) + with open(filename, "w") as script: + print >>script, "import sys" + print >>script, "del sys.modules['__main__']" + assert_python_ok(filename) + + def test_main(): test.test_support.run_unittest(CmdLineTest) test.test_support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS index b2ad14b50d3..16ddf41e288 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ What's New in Python 2.7.4 Core and Builtins ----------------- +- Issue #15001: fix segfault on "del sys.modules['__main__']". Patch by Victor + Stinner. + - Issue #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u'foo'[0]) in order to produce compatible pyc files between narrow and wide builds. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index afb4c510174..a2e1e745897 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -907,19 +907,20 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret, len; + int set_file_name = 0, len, ret = -1; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; + Py_INCREF(m); d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f = PyString_FromString(filename); if (f == NULL) - return -1; + goto done; if (PyDict_SetItemString(d, "__file__", f) < 0) { Py_DECREF(f); - return -1; + goto done; } set_file_name = 1; Py_DECREF(f); @@ -932,7 +933,6 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, fclose(fp); if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - ret = -1; goto done; } /* Turn on optimization if a .pyo file is given */ @@ -945,7 +945,6 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, } if (v == NULL) { PyErr_Print(); - ret = -1; goto done; } Py_DECREF(v); @@ -955,6 +954,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); + Py_DECREF(m); return ret; }