From fbaaab9d25692c4f8bee0f9f680567ba3f46632b Mon Sep 17 00:00:00 2001 From: Neal Norwitz Date: Mon, 13 Jan 2003 20:17:22 +0000 Subject: [PATCH] Backport: Fix SF bug #667147, Segmentation fault printing str subclass Fix infinite recursion which occurred when printing an object whose __str__() returned self. --- Lib/test/test_descr.py | 25 ++++++++++++++++++++++++- Misc/NEWS | 2 ++ Objects/object.c | 19 ++++++++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 565d6d9dbac2..f92bba29c3ed 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1,6 +1,6 @@ # Test enhancements related to descriptors and new-style classes -from test_support import verify, vereq, verbose, TestFailed, TESTFN +from test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout from copy import deepcopy import warnings @@ -1605,6 +1605,29 @@ def specials(): unsafecmp(1, 1L) unsafecmp(1L, 1) + class Letter(str): + def __new__(cls, letter): + if letter == 'EPS': + return str.__new__(cls) + return str.__new__(cls, letter) + def __str__(self): + if not self: + return 'EPS' + return self + + # sys.stdout needs to be the original to trigger the recursion bug + import sys + test_stdout = sys.stdout + sys.stdout = get_original_stdout() + try: + # nothing should actually be printed, this should raise an exception + print Letter('w') + except RuntimeError: + pass + else: + raise TestFailed, "expected a RuntimeError for print recursion" + sys.stdout = test_stdout + def weakrefs(): if verbose: print "Testing weak references..." import weakref diff --git a/Misc/NEWS b/Misc/NEWS index 022f53984d35..091501c9ed65 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -60,6 +60,8 @@ Release date: XX-XXX-2003 - SF #659228, fix realpath() not being exported from os.path +- SF #667147, fix crash when printing str subclass. + What's New in Python 2.2.2 (final) ? Release date: 14-Oct-2002 ==================================== diff --git a/Objects/object.c b/Objects/object.c index d68356f9e7ad..893be733cac7 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -146,10 +146,15 @@ _PyObject_Del(PyObject *op) PyObject_FREE(op); } -int -PyObject_Print(PyObject *op, FILE *fp, int flags) +/* Implementation of PyObject_Print with recursion checking */ +static int +internal_print(PyObject *op, FILE *fp, int flags, int nesting) { int ret = 0; + if (nesting > 10) { + PyErr_SetString(PyExc_RuntimeError, "print recursion"); + return -1; + } if (PyErr_CheckSignals()) return -1; #ifdef USE_STACKCHECK @@ -175,7 +180,8 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) if (s == NULL) ret = -1; else { - ret = PyObject_Print(s, fp, Py_PRINT_RAW); + ret = internal_print(s, fp, Py_PRINT_RAW, + nesting+1); } Py_XDECREF(s); } @@ -192,6 +198,13 @@ PyObject_Print(PyObject *op, FILE *fp, int flags) return ret; } +int +PyObject_Print(PyObject *op, FILE *fp, int flags) +{ + return internal_print(op, fp, flags, 0); +} + + /* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */ void _PyObject_Dump(PyObject* op) { -- 2.47.3