diff Python/modsupport.c @ 32656:391937571065 legacy-trunk

This is Pete Shinners' patch from his bug report [ 984722 ] Py_BuildValue loses reference counts on error I'm ever-so-slightly uneasy at the amount of work this can do with an exception pending, but I don't think that this can result in anything more serious than a strange error message.
author Michael W. Hudson <mwh@python.net>
date Wed, 14 Jul 2004 11:28:06 +0000
parents b6c139544c16
children fe4c627b2096
line wrap: on
line diff
--- a/Python/modsupport.c	Wed Jul 14 00:48:58 2004 +0000
+++ b/Python/modsupport.c	Wed Jul 14 11:28:06 2004 +0000
@@ -152,28 +152,32 @@
 {
 	PyObject *d;
 	int i;
+	int itemfailed = 0;
 	if (n < 0)
 		return NULL;
 	if ((d = PyDict_New()) == NULL)
 		return NULL;
+	/* Note that we can't bail immediately on error as this will leak
+	   refcounts on any 'N' arguments. */
 	for (i = 0; i < n; i+= 2) {
 		PyObject *k, *v;
 		int err;
 		k = do_mkvalue(p_format, p_va);
 		if (k == NULL) {
-			Py_DECREF(d);
-			return NULL;
+			itemfailed = 1;
+			Py_INCREF(Py_None);
+			k = Py_None;
 		}
 		v = do_mkvalue(p_format, p_va);
 		if (v == NULL) {
-			Py_DECREF(k);
-			Py_DECREF(d);
-			return NULL;
+			itemfailed = 1;
+			Py_INCREF(Py_None);
+			v = Py_None;
 		}
 		err = PyDict_SetItem(d, k, v);
 		Py_DECREF(k);
 		Py_DECREF(v);
-		if (err < 0) {
+		if (err < 0 || itemfailed) {
 			Py_DECREF(d);
 			return NULL;
 		}
@@ -194,15 +198,19 @@
 {
 	PyObject *v;
 	int i;
+	int itemfailed = 0;
 	if (n < 0)
 		return NULL;
 	if ((v = PyList_New(n)) == NULL)
 		return NULL;
+	/* Note that we can't bail immediately on error as this will leak
+	   refcounts on any 'N' arguments. */
 	for (i = 0; i < n; i++) {
 		PyObject *w = do_mkvalue(p_format, p_va);
 		if (w == NULL) {
-			Py_DECREF(v);
-			return NULL;
+			itemfailed = 1;
+			Py_INCREF(Py_None);
+			w = Py_None;
 		}
 		PyList_SetItem(v, i, w);
 	}
@@ -214,6 +222,10 @@
 	}
 	else if (endchar)
 		++*p_format;
+	if (itemfailed) {
+		Py_DECREF(v);
+		v = NULL;
+	}
 	return v;
 }
 
@@ -233,15 +245,19 @@
 {
 	PyObject *v;
 	int i;
+	int itemfailed = 0;
 	if (n < 0)
 		return NULL;
 	if ((v = PyTuple_New(n)) == NULL)
 		return NULL;
+	/* Note that we can't bail immediately on error as this will leak
+	   refcounts on any 'N' arguments. */
 	for (i = 0; i < n; i++) {
 		PyObject *w = do_mkvalue(p_format, p_va);
 		if (w == NULL) {
-			Py_DECREF(v);
-			return NULL;
+			itemfailed = 1;
+			Py_INCREF(Py_None);
+			w = Py_None;
 		}
 		PyTuple_SetItem(v, i, w);
 	}
@@ -253,6 +269,10 @@
 	}
 	else if (endchar)
 		++*p_format;
+	if (itemfailed) {
+		Py_DECREF(v);
+		v = NULL;
+	}
 	return v;
 }