]> granicus.if.org Git - python/commitdiff
#3242: fix a crash in "print", if sys.stdout is set to a custom object,
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Tue, 1 Jul 2008 20:38:04 +0000 (20:38 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Tue, 1 Jul 2008 20:38:04 +0000 (20:38 +0000)
whose write() method installs another sys.stdout.

Will backport.

Lib/test/test_file.py
Misc/NEWS
Python/ceval.c

index aab3e706cba042a83eb0a825f72a90f1a1c4b456..7cfaef76fedfaca3e231ea44e493b6814d220676 100644 (file)
@@ -503,13 +503,31 @@ class FileThreadingTests(unittest.TestCase):
         self._test_close_open_io(io_func)
 
 
+class StdoutTests(unittest.TestCase):
+
+    def test_move_stdout_on_write(self):
+        # Issue 3242: sys.stdout can be replaced (and freed) during a
+        # print statement; prevent a segfault in this case
+        save_stdout = sys.stdout
+
+        class File:
+            def write(self, data):
+                if '\n' in data:
+                    sys.stdout = save_stdout
+
+        try:
+            sys.stdout = File()
+            print "some text"
+        finally:
+            sys.stdout = save_stdout
+
 
 def test_main():
     # Historically, these tests have been sloppy about removing TESTFN.
     # So get rid of it no matter what.
     try:
         run_unittest(AutoFileTests, OtherFileTests, FileSubclassTests,
-            FileThreadingTests)
+            FileThreadingTests, StdoutTests)
     finally:
         if os.path.exists(TESTFN):
             os.unlink(TESTFN)
index af95f94affc0b46b280663b0683311b2b2e2c846..64b975190330e93d81284c52b3fb0de035928846 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@ What's New in Python 2.6 beta 2?
 Core and Builtins
 -----------------
 
+- Issue #3242: Fix a crash inside the print statement, if sys.stdout is
+  set to a custom object whose write() method happens to install
+  another file in sys.stdout.
+
 - Issue #3088: Corrected a race condition in classes derived from
   threading.local: the first member set by a thread could be saved in
   another thread's dictionary.
index 0cff157662fe78ffefe785a84c4c2a4b4a6de537..60a91b2759c574d82db22a21a659f6c6ef37ed84 100644 (file)
@@ -1617,9 +1617,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
                                                        "lost sys.stdout");
                        }
                        if (w != NULL) {
+                               Py_INCREF(w);
                                err = PyFile_WriteString("\n", w);
                                if (err == 0)
                                        PyFile_SoftSpace(w, 0);
+                               Py_DECREF(w);
                        }
                        Py_XDECREF(stream);
                        stream = NULL;