summaryrefslogtreecommitdiff
path: root/Python/modsupport.c
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2004-07-14 11:28:06 +0000
committerMichael W. Hudson <mwh@python.net>2004-07-14 11:28:06 +0000
commitc849e63eb080274f0c9ade654a7f1ffc7ecc3cf3 (patch)
tree754d650d36150e6c3f9a7b9c12904dfd16bcb47a /Python/modsupport.c
parent8cec3ab0e44a65d9bb0b70f6963defd21dbeccbf (diff)
downloadcpython-git-c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3.tar.gz
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.
Diffstat (limited to 'Python/modsupport.c')
-rw-r--r--Python/modsupport.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c
index f26d7b8eca..197d99b1d1 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;
}