Skip to content

Commit ceda6a6

Browse files
committed
python#3242: fix a crash in "print", if sys.stdout is set to a custom object,
whose write() method installs another sys.stdout. Backport of r64633
1 parent 6fa30f4 commit ceda6a6

3 files changed

Lines changed: 26 additions & 1 deletion

File tree

‎Lib/test/test_file.py‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,30 @@ def testIteration(self):
323323
os.unlink(TESTFN)
324324

325325

326+
class StdoutTests(unittest.TestCase):
327+
328+
def test_move_stdout_on_write(self):
329+
# Issue 3242: sys.stdout can be replaced (and freed) during a
330+
# print statement; prevent a segfault in this case
331+
save_stdout = sys.stdout
332+
333+
class File:
334+
def write(self, data):
335+
if '\n' in data:
336+
sys.stdout = save_stdout
337+
338+
try:
339+
sys.stdout = File()
340+
print "some text"
341+
finally:
342+
sys.stdout = save_stdout
343+
344+
326345
def test_main():
327346
# Historically, these tests have been sloppy about removing TESTFN.
328347
# So get rid of it no matter what.
329348
try:
330-
run_unittest(AutoFileTests, OtherFileTests)
349+
run_unittest(AutoFileTests, OtherFileTests, StdoutTests)
331350
finally:
332351
if os.path.exists(TESTFN):
333352
os.unlink(TESTFN)

‎Misc/NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 2.5.3?
1212
Core and builtins
1313
-----------------
1414

15+
- Issue #3242: Fix a crash inside the print statement, if sys.stdout is
16+
set to a custom object whose write() method happens to install
17+
another file in sys.stdout.
18+
1519
- Issue #3100: Corrected a crash on deallocation of a subclassed weakref which
1620
holds the last (strong) reference to its referent.
1721

‎Python/ceval.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,9 +1603,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
16031603
"lost sys.stdout");
16041604
}
16051605
if (w != NULL) {
1606+
Py_INCREF(w);
16061607
err = PyFile_WriteString("\n", w);
16071608
if (err == 0)
16081609
PyFile_SoftSpace(w, 0);
1610+
Py_DECREF(w);
16091611
}
16101612
Py_XDECREF(stream);
16111613
stream = NULL;

0 commit comments

Comments
 (0)