]> granicus.if.org Git - python/commitdiff
Fix SF bug #667147, Segmentation fault printing str subclass
authorNeal Norwitz <nnorwitz@gmail.com>
Mon, 13 Jan 2003 20:13:12 +0000 (20:13 +0000)
committerNeal Norwitz <nnorwitz@gmail.com>
Mon, 13 Jan 2003 20:13:12 +0000 (20:13 +0000)
Fix infinite recursion which occurred when printing an object
whose __str__() returned self.

Will backport

Lib/test/test_descr.py
Misc/NEWS
Objects/object.c

index 023fcc82f53e993603e19055ad9408a8354e03ed..da4bd033107e2efa61ade9c9b9dd38edd240bb21 100644 (file)
@@ -1,6 +1,6 @@
 # Test enhancements related to descriptors and new-style classes
 
-from test.test_support import verify, vereq, verbose, TestFailed, TESTFN
+from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout
 from copy import deepcopy
 import warnings
 
@@ -1821,6 +1821,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
index 1fa1c8c44e98d5d569f63d94dd45528804eebea9..5f415d49baf7ba3d11fd7e6a3e29e053b637d594 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,9 @@ Core and builtins
   Passing None is semantically identical to calling sort() with no
   arguments.
 
+- Fixed crash when printing a subclass of str and __str__ returned self.
+  See SF bug #667147.
+
 Extension modules
 -----------------
 
index 33286435e90b3e13e3c825f5d7b0cb041628a86f..e3234deca72dd5fded659606fba9577a3bd9b5e3 100644 (file)
@@ -158,10 +158,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
@@ -187,7 +192,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);
                }
@@ -204,6 +210,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)
 {