From 06b1db942f6d5b3ee5fc1fde2823943bbda4b7d9 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 3 Apr 2014 02:34:43 +0100 Subject: [PATCH] Fixed overflow opening a lobject with an oid not fitting in a signed int Fixes :ticket:`203`. Conflicts: NEWS --- NEWS | 2 ++ psycopg/connection_type.c | 10 +++++----- psycopg/lobject_type.c | 6 +++--- tests/test_lobject.py | 6 ++++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 0b5c3772..1dc3a5d5 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ What's new in psycopg 2.4.7 failing to connect (from :ticket:`#192` discussion). - Don't segfault using poorly defined cursor subclasses which forgot to call the superclass init (:ticket:`#195`). + - Fixed overflow opening a lobject with an oid not fitting in a signed int + (:ticket:`#203`). - Fixed debug build on Windows, thanks to James Emerton. diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index 54e995a6..368c907f 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -696,7 +696,7 @@ psyco_conn_get_parameter_status(connectionObject *self, PyObject *args) static PyObject * 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 *smode = ""; PyObject *factory = (PyObject *)&lobjectType; @@ -705,7 +705,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds) static char *kwlist[] = {"oid", "mode", "new_oid", "new_file", "cursor_factory", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, keywds, "|izizO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, keywds, "|IzIzO", kwlist, &oid, &smode, &new_oid, &new_file, &factory)) { return NULL; @@ -717,16 +717,16 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds) EXC_IF_TPC_PREPARED(self, lobject); 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); Dprintf("psyco_conn_lobject: parameters: new_oid = %d, new_file = %s", new_oid, new_file); if (new_file) - obj = PyObject_CallFunction(factory, "Oisis", + obj = PyObject_CallFunction(factory, "OIsIs", self, oid, smode, new_oid, new_file); else - obj = PyObject_CallFunction(factory, "Oisi", + obj = PyObject_CallFunction(factory, "OIsI", self, oid, smode, new_oid); if (obj == NULL) return NULL; diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c index f587f81c..4a47721f 100644 --- a/psycopg/lobject_type.c +++ b/psycopg/lobject_type.c @@ -375,18 +375,18 @@ lobject_dealloc(PyObject* obj) static int 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 *new_file = NULL; PyObject *conn = NULL; - if (!PyArg_ParseTuple(args, "O!|iziz", + if (!PyArg_ParseTuple(args, "O!|IzIz", &connectionType, &conn, &oid, &smode, &new_oid, &new_file)) return -1; 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 * diff --git a/tests/test_lobject.py b/tests/test_lobject.py index 4a8c980e..597e07c3 100755 --- a/tests/test_lobject.py +++ b/tests/test_lobject.py @@ -381,6 +381,12 @@ class LargeObjectTests(LargeObjectMixin, unittest.TestCase): finally: 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) decorate_all_tests(LargeObjectTests, skip_if_green)