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

Fixes 🎫`203`.

Conflicts:

	NEWS
This commit is contained in:
Daniele Varrazzo 2014-04-03 02:34:43 +01:00
parent 0f6122242c
commit 06b1db942f
4 changed files with 16 additions and 8 deletions

2
NEWS
View File

@ -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.

View File

@ -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;

View File

@ -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 *

View File

@ -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)