diff options
author | Michael W. Hudson <mwh@python.net> | 2004-07-14 11:28:06 (GMT) |
---|---|---|
committer | Michael W. Hudson <mwh@python.net> | 2004-07-14 11:28:06 (GMT) |
commit | c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3 (patch) | |
tree | 754d650d36150e6c3f9a7b9c12904dfd16bcb47a | |
parent | 8cec3ab0e44a65d9bb0b70f6963defd21dbeccbf (diff) | |
download | cpython-c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3.zip cpython-c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3.tar.gz cpython-c849e63eb080274f0c9ade654a7f1ffc7ecc3cf3.tar.bz2 |
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.
-rw-r--r-- | Python/modsupport.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c index f26d7b8..197d99b 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; } |