From e9462c72bd3db9daca682bc7f993f9c77a4022db Mon Sep 17 00:00:00 2001
From: Georg Brandl <georg@python.org>
Date: Fri, 4 Aug 2006 18:03:37 +0000
Subject: [PATCH] Change fix for segfaulting property(), add a NEWS entry and a
 test.

---
 Lib/test/test_descr.py    | 10 ++++++++++
 Misc/NEWS                 |  2 ++
 Modules/_testcapimodule.c |  9 +++++++++
 Objects/descrobject.c     | 22 ++++++++++++----------
 4 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 6484ef1a75..e9286b0e6a 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -2024,6 +2024,16 @@ def properties():
         prop2 = property(fset=setter)
         vereq(prop2.__doc__, None)
 
+    # this segfaulted in 2.5b2
+    try:
+        import _testcapi
+    except ImportError:
+        pass
+    else:
+        class X(object):
+            p = property(_testcapi.test_with_docstring)
+
+
 def supers():
     if verbose: print "Testing super..."
 
diff --git a/Misc/NEWS b/Misc/NEWS
index 3c1ba7f1de..5b7830968a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,8 @@ Core and builtins
   in the byte code and co_consts even if they were not used, ie
   immediately popped off the stack.
 
+- Fixed a reference-counting problem in property().
+
 
 Library
 -------
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index b90ca5763c..f5f3ab23bd 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -706,6 +706,13 @@ test_string_from_format(PyObject *self, PyObject *args)
 #undef CHECK_1_FORMAT
 }
 
+/* This is here to provide a docstring for test_descr. */
+static PyObject *
+test_with_docstring(PyObject *self)
+{
+	Py_RETURN_NONE;
+}
+
 static PyMethodDef TestMethods[] = {
 	{"raise_exception",	raise_exception,		 METH_VARARGS},
 	{"test_config",		(PyCFunction)test_config,	 METH_NOARGS},
@@ -716,6 +723,8 @@ static PyMethodDef TestMethods[] = {
 	{"test_k_code",		(PyCFunction)test_k_code,	 METH_NOARGS},
 	{"test_null_strings",	(PyCFunction)test_null_strings,	 METH_NOARGS},
 	{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
+	{"test_with_docstring", (PyCFunction)test_with_docstring, METH_NOARGS,
+	 PyDoc_STR("This is a pretty normal docstring.")},
 
 	{"getargs_tuple",	getargs_tuple,			 METH_VARARGS},
 	{"getargs_b",		getargs_b,			 METH_VARARGS},
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 1fe62812a2..914b6d35a1 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1190,19 +1190,21 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds)
 	if (del == Py_None)
 		del = NULL;
 
-	/* if no docstring given and the getter has one, use that one */
-	if ((doc == NULL || doc == Py_None) && get != NULL && 
-	    PyObject_HasAttrString(get, "__doc__")) {
-		doc = PyObject_GetAttrString(get, "__doc__");
-		if (doc == NULL)
-			return -1;
-	} else {
-		Py_XINCREF(doc);
-	}
-
 	Py_XINCREF(get);
 	Py_XINCREF(set);
 	Py_XINCREF(del);
+	Py_XINCREF(doc);
+
+	/* if no docstring given and the getter has one, use that one */
+	if ((doc == NULL || doc == Py_None) && get != NULL) {
+		PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");
+		if (get_doc != NULL) {
+			Py_XDECREF(doc);
+			doc = get_doc;  /* get_doc already INCREF'd by GetAttr */
+		} else {
+			PyErr_Clear();
+		}
+	}
 
 	gs->prop_get = get;
 	gs->prop_set = set;
-- 
2.40.0