Patch 3/4: _mysql.c reference counting and exception issues

This patch fixes a reference leak and improves the error handling in the converter mapping code. Rather accidentially it also drops the cleanup: label and the gotos ;)

https://sourceforge.net/p/mysql-python/patches/79/
This commit is contained in:
André Malo
2012-10-03 13:17:35 -04:00
committed by farcepest
parent 1c33baf352
commit c05a2c6a50

View File

@ -407,8 +407,13 @@ _mysql_ResultObject_Initialize(
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist,
&conn, &use, &conv)) &conn, &use, &conv))
return -1; return -1;
if (!conv) conv = PyDict_New(); if (!conv) {
if (!conv) return -1; if (!(conv = PyDict_New()))
return -1;
}
else
Py_INCREF(conv);
self->conn = (PyObject *) conn; self->conn = (PyObject *) conn;
Py_INCREF(conn); Py_INCREF(conn);
self->use = use; self->use = use;
@ -425,31 +430,47 @@ _mysql_ResultObject_Initialize(
return -1; return -1;
} }
self->converter = PyTuple_New(0); self->converter = PyTuple_New(0);
Py_DECREF(conv);
return 0; return 0;
} }
n = mysql_num_fields(result); n = mysql_num_fields(result);
self->nfields = n; self->nfields = n;
if (!(self->converter = PyTuple_New(n))) return -1; if (!(self->converter = PyTuple_New(n))) {
Py_DECREF(conv);
return -1;
}
fields = mysql_fetch_fields(result); fields = mysql_fetch_fields(result);
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
PyObject *tmp, *fun; PyObject *tmp, *fun;
tmp = PyInt_FromLong((long) fields[i].type); tmp = PyInt_FromLong((long) fields[i].type);
if (!tmp) return -1; if (!tmp) {
Py_DECREF(conv);
return -1;
}
fun = PyObject_GetItem(conv, tmp); fun = PyObject_GetItem(conv, tmp);
Py_DECREF(tmp); Py_DECREF(tmp);
if (!fun) { if (!fun) {
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
Py_DECREF(conv);
return -1;
}
PyErr_Clear(); PyErr_Clear();
}
fun = Py_None; fun = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
} }
if (PySequence_Check(fun)) { else if (PySequence_Check(fun)) {
int j, n2=PySequence_Size(fun); int j, n2=PySequence_Size(fun);
PyObject *fun2=NULL; PyObject *fun2=NULL;
for (j=0; j<n2; j++) { for (j=0; j<n2; j++) {
PyObject *t = PySequence_GetItem(fun, j); PyObject *t = PySequence_GetItem(fun, j);
if (!t) continue; if (!t) {
if (!PyTuple_Check(t)) goto cleanup; Py_DECREF(fun);
if (PyTuple_GET_SIZE(t) == 2) { Py_DECREF(conv);
return -1;
}
if (PyTuple_Check(t) && PyTuple_GET_SIZE(t) == 2) {
long mask; long mask;
PyObject *pmask=NULL; PyObject *pmask=NULL;
pmask = PyTuple_GET_ITEM(t, 0); pmask = PyTuple_GET_ITEM(t, 0);
@ -461,14 +482,13 @@ _mysql_ResultObject_Initialize(
break; break;
} }
else { else {
goto cleanup; fun2 = NULL;
} }
} else { } else {
Py_DECREF(t); Py_DECREF(t);
break; break;
} }
} }
cleanup:
Py_DECREF(t); Py_DECREF(t);
} }
if (!fun2) fun2 = Py_None; if (!fun2) fun2 = Py_None;
@ -478,6 +498,8 @@ _mysql_ResultObject_Initialize(
} }
PyTuple_SET_ITEM(self->converter, i, fun); PyTuple_SET_ITEM(self->converter, i, fun);
} }
Py_DECREF(conv);
return 0; return 0;
} }