summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>2008-07-01 20:38:04 (GMT)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>2008-07-01 20:38:04 (GMT)
commitbdd941fac3631e0c971d6c1a4e9f9b39a787b14e (patch)
tree05028f6a4f65f7214d266282fdb78480e3d68ef3
parentdbd0ae383d7e23dfe219704605b55f556d2ee914 (diff)
downloadcpython-bdd941fac3631e0c971d6c1a4e9f9b39a787b14e.zip
cpython-bdd941fac3631e0c971d6c1a4e9f9b39a787b14e.tar.gz
cpython-bdd941fac3631e0c971d6c1a4e9f9b39a787b14e.tar.bz2
#3242: fix a crash in "print", if sys.stdout is set to a custom object,
whose write() method installs another sys.stdout. Will backport.
-rw-r--r--Lib/test/test_file.py20
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/ceval.c2
3 files changed, 25 insertions, 1 deletions
diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py
index aab3e70..7cfaef7 100644
--- a/Lib/test/test_file.py
+++ b/Lib/test/test_file.py
@@ -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)
diff --git a/Misc/NEWS b/Misc/NEWS
index af95f94..64b9751 100644
--- 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.
diff --git a/Python/ceval.c b/Python/ceval.c
index 0cff157..60a91b2 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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;