mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-10 19:16:34 +03:00
Fixed handling large Oid values
Oid is defined as unsigned 32. On some Python implementations (probably the ones where maxint = 2 ** 31) this can cause int overflow for large values (see #961). On my 64 box it doesn't seem the case. Oid handling was sloppy here and there (messages, casts...): trying to use uint everywhere, and added a couple of helper macros to treat Oid consistently. Close #961.
This commit is contained in:
parent
4d10f1235f
commit
80df0553a6
6
NEWS
6
NEWS
|
@ -4,8 +4,10 @@ Current release
|
|||
What's new in psycopg 2.8.4
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Don't swallow keyboard interrupts on connect when a password is specified
|
||||
in the connection string (:ticket:`#898`).
|
||||
- Don't swallow keyboard interrupts on connect when a password is specified
|
||||
in the connection string (:ticket:`#898`).
|
||||
- Fixed int overflow for large values in `~psycopg2.extensions.Column.table_oid`
|
||||
and `~psycopg2.extensions.Column.type_code` (:ticket:`961).
|
||||
|
||||
|
||||
What's new in psycopg 2.8.3
|
||||
|
|
|
@ -968,7 +968,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
|
|||
Dprintf("psyco_conn_lobject: new lobject for connection at %p", self);
|
||||
Dprintf("psyco_conn_lobject: parameters: oid = %u, mode = %s",
|
||||
oid, smode);
|
||||
Dprintf("psyco_conn_lobject: parameters: new_oid = %d, new_file = %s",
|
||||
Dprintf("psyco_conn_lobject: parameters: new_oid = %u, new_file = %s",
|
||||
new_oid, new_file);
|
||||
|
||||
if (new_file)
|
||||
|
|
|
@ -1827,7 +1827,7 @@ static struct PyMemberDef cursorObject_members[] = {
|
|||
"Number of records ``iter(cur)`` must fetch per network roundtrip."},
|
||||
{"description", T_OBJECT, OFFSETOF(description), READONLY,
|
||||
"Cursor description as defined in DBAPI-2.0."},
|
||||
{"lastrowid", T_LONG, OFFSETOF(lastoid), READONLY,
|
||||
{"lastrowid", T_OID, OFFSETOF(lastoid), READONLY,
|
||||
"The ``oid`` of the last row inserted by the cursor."},
|
||||
/* DBAPI-2.0 extensions */
|
||||
{"rownumber", T_LONG, OFFSETOF(row), READONLY,
|
||||
|
|
|
@ -176,7 +176,7 @@ lobject_open(lobjectObject *self, connectionObject *conn,
|
|||
self->oid = lo_creat(self->conn->pgconn, INV_READ | INV_WRITE);
|
||||
}
|
||||
|
||||
Dprintf("lobject_open: large object created with oid = %d",
|
||||
Dprintf("lobject_open: large object created with oid = %u",
|
||||
self->oid);
|
||||
|
||||
if (self->oid == InvalidOid) {
|
||||
|
|
|
@ -327,7 +327,7 @@ static struct PyMethodDef lobjectObject_methods[] = {
|
|||
/* object member list */
|
||||
|
||||
static struct PyMemberDef lobjectObject_members[] = {
|
||||
{"oid", T_UINT, offsetof(lobjectObject, oid), READONLY,
|
||||
{"oid", T_OID, offsetof(lobjectObject, oid), READONLY,
|
||||
"The backend OID associated to this lobject."},
|
||||
{"mode", T_STRING, offsetof(lobjectObject, smode), READONLY,
|
||||
"Open mode."},
|
||||
|
@ -368,7 +368,7 @@ lobject_setup(lobjectObject *self, connectionObject *conn,
|
|||
|
||||
Dprintf("lobject_setup: good lobject object at %p, refcnt = "
|
||||
FORMAT_CODE_PY_SSIZE_T, self, Py_REFCNT(self));
|
||||
Dprintf("lobject_setup: oid = %d, fd = %d", self->oid, self->fd);
|
||||
Dprintf("lobject_setup: oid = %u, fd = %d", self->oid, self->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -995,9 +995,9 @@ _get_cast(cursorObject *curs, PGresult *pgres, int i)
|
|||
PyObject *rv = NULL;
|
||||
|
||||
Oid ftype = PQftype(pgres, i);
|
||||
if (!(type = PyInt_FromLong(ftype))) { goto exit; }
|
||||
if (!(type = PyLong_FromOid(ftype))) { goto exit; }
|
||||
|
||||
Dprintf("_pq_fetch_tuples: looking for cast %d:", ftype);
|
||||
Dprintf("_pq_fetch_tuples: looking for cast %u:", ftype);
|
||||
if (!(cast = curs_get_cast(curs, type))) { goto exit; }
|
||||
|
||||
/* else if we got binary tuples and if we got a field that
|
||||
|
@ -1006,11 +1006,11 @@ _get_cast(cursorObject *curs, PGresult *pgres, int i)
|
|||
*/
|
||||
if (cast == psyco_default_binary_cast && PQbinaryTuples(pgres)) {
|
||||
Dprintf("_pq_fetch_tuples: Binary cursor and "
|
||||
"binary field: %i using default cast", ftype);
|
||||
"binary field: %u using default cast", ftype);
|
||||
cast = psyco_default_cast;
|
||||
}
|
||||
|
||||
Dprintf("_pq_fetch_tuples: using cast at %p for type %d", cast, ftype);
|
||||
Dprintf("_pq_fetch_tuples: using cast at %p for type %u", cast, ftype);
|
||||
|
||||
/* success */
|
||||
Py_INCREF(cast);
|
||||
|
@ -1041,7 +1041,7 @@ _make_column(connectionObject *conn, PGresult *pgres, int i)
|
|||
/* fill the type and name fields */
|
||||
{
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong(ftype))) {
|
||||
if (!(tmp = PyLong_FromOid(ftype))) {
|
||||
goto exit;
|
||||
}
|
||||
column->type_code = tmp;
|
||||
|
@ -1099,7 +1099,7 @@ _make_column(connectionObject *conn, PGresult *pgres, int i)
|
|||
/* table_oid, table_column */
|
||||
if (ftable != InvalidOid) {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong((long)ftable))) { goto exit; }
|
||||
if (!(tmp = PyLong_FromOid(ftable))) { goto exit; }
|
||||
column->table_oid = tmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,11 @@ typedef unsigned long Py_uhash_t;
|
|||
|
||||
#define INIT_MODULE(m) init ## m
|
||||
|
||||
/* fix #961, but don't change all types to longs. Sure someone will complain. */
|
||||
#define PyLong_FromOid(x) (((x) & 0x80000000) ? \
|
||||
PyLong_FromUnsignedLong((unsigned long)(x)) : \
|
||||
PyInt_FromLong((x)))
|
||||
|
||||
#endif /* PY_2 */
|
||||
|
||||
#if PY_3
|
||||
|
@ -133,6 +138,11 @@ typedef unsigned long Py_uhash_t;
|
|||
|
||||
#define INIT_MODULE(m) PyInit_ ## m
|
||||
|
||||
#define PyLong_FromOid(x) (PyLong_FromUnsignedLong((unsigned long)(x)))
|
||||
|
||||
#endif /* PY_3 */
|
||||
|
||||
/* expose Oid attributes in Python C objects */
|
||||
#define T_OID T_UINT
|
||||
|
||||
#endif /* !defined(PSYCOPG_PYTHON_H) */
|
||||
|
|
Loading…
Reference in New Issue
Block a user