Raise TypeError if the dict in callproc param contains non-strings

Check-and-conversion chain fixed and simplified. 'spname' was a
reference leak.
This commit is contained in:
Daniele Varrazzo 2014-06-05 02:18:05 +02:00 committed by mrmilosz
parent a3eed9c9f5
commit d297976d6d
2 changed files with 15 additions and 29 deletions

View File

@ -1028,8 +1028,6 @@ psyco_curs_callproc(cursorObject *self, PyObject *args)
int using_dict; int using_dict;
#if PG_VERSION_HEX >= 0x090000 #if PG_VERSION_HEX >= 0x090000
PyObject *pname = NULL; PyObject *pname = NULL;
PyObject *spname = NULL;
PyObject *bpname = NULL;
PyObject *pnames = NULL; PyObject *pnames = NULL;
char *cpname = NULL; char *cpname = NULL;
char **scpnames = NULL; char **scpnames = NULL;
@ -1076,37 +1074,24 @@ psyco_curs_callproc(cursorObject *self, PyObject *args)
for (i = 0; i < nparameters; i++) { for (i = 0; i < nparameters; i++) {
/* all errors are RuntimeErrors as they should never occur */ /* all errors are RuntimeErrors as they should never occur */
if (!(pname = PyList_GetItem(pnames, i))) { if (!(pname = PyList_GetItem(pnames, i))) { goto exit; }
Py_INCREF(pname); /* was borrowed */
/* this also makes a check for keys being strings */
if (!(pname = psycopg_ensure_bytes(pname))) { goto exit; }
if (!(cpname = Bytes_AsString(pname))) { goto exit; }
if (!(scpnames[i] = PQescapeIdentifier(
self->conn->pgconn, cpname, strlen(cpname)))) {
goto exit; goto exit;
} }
if (!(spname = PyObject_Str(pname))) { Py_CLEAR(pname);
goto exit;
}
/* this is the only function here that returns a new reference */
if (!(bpname = psycopg_ensure_bytes(spname))) {
goto exit;
}
if (!(cpname = Bytes_AsString(bpname))) {
Py_XDECREF(bpname);
goto exit;
}
if (!(scpnames[i] = PQescapeIdentifier(self->conn->pgconn, cpname,
strlen(cpname)))) {
Py_XDECREF(bpname);
goto exit;
}
Py_XDECREF(bpname);
sl += strlen(scpnames[i]); sl += strlen(scpnames[i]);
} }
sql = (char*)PyMem_Malloc(sl); if (!(sql = (char*)PyMem_Malloc(sl))) {
if (sql == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
goto exit; goto exit;
} }
@ -1170,6 +1155,7 @@ exit:
} }
} }
PyMem_Del(scpnames); PyMem_Del(scpnames);
Py_XDECREF(pname);
Py_XDECREF(pnames); Py_XDECREF(pnames);
#endif #endif
Py_XDECREF(operation); Py_XDECREF(operation);

View File

@ -520,9 +520,9 @@ class CursorTests(ConnectingTestCase):
({ paramname: 2, 'foo': 'bar' }, psycopg2.ProgrammingError), ({ paramname: 2, 'foo': 'bar' }, psycopg2.ProgrammingError),
({ paramname: '2' }, psycopg2.ProgrammingError), ({ paramname: '2' }, psycopg2.ProgrammingError),
({ paramname: 'two' }, psycopg2.ProgrammingError), ({ paramname: 'two' }, psycopg2.ProgrammingError),
({ 'bjørn': 2 }, psycopg2.ProgrammingError), ({ u'bj\xc3rn': 2 }, psycopg2.ProgrammingError),
({ 3: 2 }, psycopg2.ProgrammingError), ({ 3: 2 }, TypeError),
({ self: 2 }, psycopg2.ProgrammingError), ({ self: 2 }, TypeError),
] ]
for parameter_sequence, exception in failing_cases: for parameter_sequence, exception in failing_cases:
self.assertRaises(exception, cur.callproc, procname, parameter_sequence) self.assertRaises(exception, cur.callproc, procname, parameter_sequence)