From c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3 Mon Sep 17 00:00:00 2001 From: "Michael W. Hudson" Date: Wed, 14 Jul 2004 11:28:06 +0000 Subject: [PATCH] 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. --- Python/modsupport.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/Python/modsupport.c b/Python/modsupport.c index f26d7b8eca2..197d99b1d1f 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -152,28 +152,32 @@ do_mkdict(char **p_format, va_list *p_va, int endchar, int n) { 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 @@ do_mklist(char **p_format, va_list *p_va, int endchar, int n) { 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 @@ do_mklist(char **p_format, va_list *p_va, int endchar, int n) } else if (endchar) ++*p_format; + if (itemfailed) { + Py_DECREF(v); + v = NULL; + } return v; } @@ -233,15 +245,19 @@ do_mktuple(char **p_format, va_list *p_va, int endchar, int n) { 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 @@ do_mktuple(char **p_format, va_list *p_va, int endchar, int n) } else if (endchar) ++*p_format; + if (itemfailed) { + Py_DECREF(v); + v = NULL; + } return v; }