]> granicus.if.org Git - python/commitdiff
Issue2297: Fix a stack overflow in Windows caused by -v and -vv. When python is...
authorTrent Nelson <trent.nelson@snakebite.org>
Wed, 19 Mar 2008 06:45:48 +0000 (06:45 +0000)
committerTrent Nelson <trent.nelson@snakebite.org>
Wed, 19 Mar 2008 06:45:48 +0000 (06:45 +0000)
Kudos to Douglas Greiman for reporting the issue and providing a patch and test case.

Lib/test/test_cmd_line.py
Python/pythonrun.c

index db94a40969642c637d84f6dc6fa519846ce7f462..19089a44aa6d5a9ffe35227e1d1a6c6d7ac5232d 100644 (file)
@@ -13,18 +13,25 @@ def _spawn_python(*args):
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
 def _kill_python(p):
+    return _kill_python_and_exit_code(p)[0]
+
+def _kill_python_and_exit_code(p):
     p.stdin.close()
     data = p.stdout.read()
     p.stdout.close()
     # try to cleanup the child so we don't appear to leak when running
     # with regrtest -R.  This should be a no-op on Windows.
     subprocess._cleanup()
-    return data
+    returncode = p.wait()
+    return data, returncode
 
 class CmdLineTest(unittest.TestCase):
     def start_python(self, *args):
+        return self.start_python_and_exit_code(*args)[0]
+
+    def start_python_and_exit_code(self, *args):
         p = _spawn_python(*args)
-        return _kill_python(p)
+        return _kill_python_and_exit_code(p)
 
     def exit_code(self, *args):
         cmd_line = [sys.executable, '-E']
@@ -61,6 +68,17 @@ class CmdLineTest(unittest.TestCase):
         version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
         self.assertTrue(self.start_python('-V').startswith(version))
 
+    def test_verbose(self):
+        # -v causes imports to write to stderr.  If the write to
+        # stderr itself causes an import to happen (for the output
+        # codec), a recursion loop can occur.
+        data, rc = self.start_python_and_exit_code('-v')
+        self.assertEqual(rc, 0)
+        self.assertTrue(b'stack overflow' not in data)
+        data, rc = self.start_python_and_exit_code('-vv')
+        self.assertEqual(rc, 0)
+        self.assertTrue(b'stack overflow' not in data)
+
     def test_run_module(self):
         # Test expected operation of the '-m' switch
         # Switch needs an argument
index 6af7aec75fd3f9a95ee0c1e6a2624d1633b93c32..d65d12d1302e4f6d3e91ba1c6de2a9ba47ae4ea6 100644 (file)
@@ -512,7 +512,7 @@ Py_Finalize(void)
        /* reset file system default encoding */
        if (!Py_HasFileSystemDefaultEncoding) {
                free((char*)Py_FileSystemDefaultEncoding);
-               Py_FileSystemDefaultEncoding = NULL;
+               Py_FileSystemDefaultEncoding = NULL;
        }
 
        /* XXX Still allocated:
@@ -733,6 +733,7 @@ initstdio(void)
        PyObject *m;
        PyObject *std = NULL;
        int status = 0, fd;
+       PyObject * encoding_attr;
 
        /* Hack to avoid a nasty recursion issue when Python is invoked
           in verbose mode: pre-import the Latin-1 and UTF-8 codecs */
@@ -823,6 +824,19 @@ initstdio(void)
                        goto error;
                }
        } /* if (fd < 0) */
+
+       /* Same as hack above, pre-import stderr's codec to avoid recursion
+          when import.c tries to write to stderr in verbose mode. */
+       encoding_attr = PyObject_GetAttrString(std, "encoding");
+       if (encoding_attr != NULL) {
+               const char * encoding;
+               encoding = PyUnicode_AsString(encoding_attr);
+               if (encoding != NULL) {
+                       _PyCodec_Lookup(encoding);
+               }
+       }
+       PyErr_Clear();  /* Not a fatal error if codec isn't available */
+
        PySys_SetObject("__stderr__", std);
        PySys_SetObject("stderr", std);
        Py_DECREF(std);
@@ -1900,8 +1914,8 @@ PyOS_CheckStack(void)
                alloca(PYOS_STACK_MARGIN * sizeof(void*));
                return 0;
        } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
-                       EXCEPTION_EXECUTE_HANDLER : 
-                       EXCEPTION_CONTINUE_SEARCH) {
+                       EXCEPTION_EXECUTE_HANDLER : 
+                       EXCEPTION_CONTINUE_SEARCH) {
                int errcode = _resetstkoflw();
                if (errcode)
                {