Fixed overflow opening a lobject with an oid not fitting in a signed int

Fixes 🎫`203`.
This commit is contained in:
Daniele Varrazzo 2014-04-03 02:34:43 +01:00
parent dfacc483b5
commit a8fdc74090
4 changed files with 16 additions and 8 deletions

2
NEWS
View File

@ -19,6 +19,8 @@ What's new in psycopg 2.5.3
Adam Petrovich for the bug report and diagnosis. Adam Petrovich for the bug report and diagnosis.
- Fixed handling of dsn and closed attributes in connection subclasses - Fixed handling of dsn and closed attributes in connection subclasses
failing to connect (from :ticket:`#192` discussion). failing to connect (from :ticket:`#192` discussion).
- Fixed overflow opening a lobject with an oid not fitting in a signed int
(:ticket:`203`).
- Don't segfault using poorly defined cursor subclasses which forgot to call - Don't segfault using poorly defined cursor subclasses which forgot to call
the superclass init (:ticket:`#195`). the superclass init (:ticket:`#195`).
- Fixed debug build on Windows, thanks to James Emerton. - Fixed debug build on Windows, thanks to James Emerton.

View File

@ -748,7 +748,7 @@ psyco_conn_get_parameter_status(connectionObject *self, PyObject *args)
static PyObject * static PyObject *
psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds) psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
{ {
int oid = (int)InvalidOid, new_oid = (int)InvalidOid; Oid oid = InvalidOid, new_oid = InvalidOid;
const char *new_file = NULL; const char *new_file = NULL;
const char *smode = ""; const char *smode = "";
PyObject *factory = (PyObject *)&lobjectType; PyObject *factory = (PyObject *)&lobjectType;
@ -757,7 +757,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
static char *kwlist[] = {"oid", "mode", "new_oid", "new_file", static char *kwlist[] = {"oid", "mode", "new_oid", "new_file",
"cursor_factory", NULL}; "cursor_factory", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|izizO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, keywds, "|IzIzO", kwlist,
&oid, &smode, &new_oid, &new_file, &oid, &smode, &new_oid, &new_file,
&factory)) { &factory)) {
return NULL; return NULL;
@ -769,16 +769,16 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
EXC_IF_TPC_PREPARED(self, lobject); EXC_IF_TPC_PREPARED(self, lobject);
Dprintf("psyco_conn_lobject: new lobject for connection at %p", self); Dprintf("psyco_conn_lobject: new lobject for connection at %p", self);
Dprintf("psyco_conn_lobject: parameters: oid = %d, mode = %s", Dprintf("psyco_conn_lobject: parameters: oid = %u, mode = %s",
oid, smode); oid, smode);
Dprintf("psyco_conn_lobject: parameters: new_oid = %d, new_file = %s", Dprintf("psyco_conn_lobject: parameters: new_oid = %d, new_file = %s",
new_oid, new_file); new_oid, new_file);
if (new_file) if (new_file)
obj = PyObject_CallFunction(factory, "Oisis", obj = PyObject_CallFunction(factory, "OIsIs",
self, oid, smode, new_oid, new_file); self, oid, smode, new_oid, new_file);
else else
obj = PyObject_CallFunction(factory, "Oisi", obj = PyObject_CallFunction(factory, "OIsI",
self, oid, smode, new_oid); self, oid, smode, new_oid);
if (obj == NULL) return NULL; if (obj == NULL) return NULL;

View File

@ -371,18 +371,18 @@ lobject_dealloc(PyObject* obj)
static int static int
lobject_init(PyObject *obj, PyObject *args, PyObject *kwds) lobject_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
int oid = (int)InvalidOid, new_oid = (int)InvalidOid; Oid oid = InvalidOid, new_oid = InvalidOid;
const char *smode = ""; const char *smode = "";
const char *new_file = NULL; const char *new_file = NULL;
PyObject *conn = NULL; PyObject *conn = NULL;
if (!PyArg_ParseTuple(args, "O!|iziz", if (!PyArg_ParseTuple(args, "O!|IzIz",
&connectionType, &conn, &connectionType, &conn,
&oid, &smode, &new_oid, &new_file)) &oid, &smode, &new_oid, &new_file))
return -1; return -1;
return lobject_setup((lobjectObject *)obj, return lobject_setup((lobjectObject *)obj,
(connectionObject *)conn, (Oid)oid, smode, (Oid)new_oid, new_file); (connectionObject *)conn, oid, smode, new_oid, new_file);
} }
static PyObject * static PyObject *

View File

@ -373,6 +373,12 @@ class LargeObjectTests(LargeObjectTestCase):
finally: finally:
self.conn.tpc_commit() self.conn.tpc_commit()
def test_large_oid(self):
# Test we don't overflow with an oid not fitting a signed int
try:
self.conn.lobject(0xFFFFFFFE)
except psycopg2.OperationalError:
pass
decorate_all_tests(LargeObjectTests, skip_if_no_lo, skip_lo_if_green) decorate_all_tests(LargeObjectTests, skip_if_no_lo, skip_lo_if_green)