* psycopg/adapter_binary.c (binary_quote): apply Brandon Rhodes'

patch from ticket #209 to check return value from
	PyObject_AsCharBuffer().  This fixes the segfault.
	(binary_quote): switch from PyObject_AsCharBuffer() to
	PyObject_AsReadBuffer() to support buffer objects that don't
	implement the bf_getcharbuf protocol.

	* tests/types_basic.py (TypesBasicTests.testBinary): Test round
	tripping of bytea buffers.  Currently segfaults.
This commit is contained in:
James Henstridge 2008-01-10 22:19:23 +00:00
parent 729117af8b
commit 86597f6939
3 changed files with 19 additions and 3 deletions

View File

@ -1,5 +1,15 @@
2008-01-11 James Henstridge <james@jamesh.id.au> 2008-01-11 James Henstridge <james@jamesh.id.au>
* psycopg/adapter_binary.c (binary_quote): apply Brandon Rhodes'
patch from ticket #209 to check return value from
PyObject_AsCharBuffer(). This fixes the segfault.
(binary_quote): switch from PyObject_AsCharBuffer() to
PyObject_AsReadBuffer() to support buffer objects that don't
implement the bf_getcharbuf protocol.
* tests/types_basic.py (TypesBasicTests.testBinary): Test round
tripping of bytea buffers. Currently segfaults.
* psycopg/connection_int.c (conn_close): fix for new * psycopg/connection_int.c (conn_close): fix for new
pq_abort_locked() prototype. pq_abort_locked() prototype.
(conn_switch_isolation_level): fix for new pq_abort_locked() (conn_switch_isolation_level): fix for new pq_abort_locked()

View File

@ -141,7 +141,9 @@ binary_quote(binaryObject *self)
/* if we got a plain string or a buffer we escape it and save the buffer */ /* if we got a plain string or a buffer we escape it and save the buffer */
if (PyString_Check(self->wrapped) || PyBuffer_Check(self->wrapped)) { if (PyString_Check(self->wrapped) || PyBuffer_Check(self->wrapped)) {
/* escape and build quoted buffer */ /* escape and build quoted buffer */
PyObject_AsCharBuffer(self->wrapped, &buffer, &buffer_len); if (PyObject_AsReadBuffer(self->wrapped, (const void **)&buffer,
&buffer_len) < 0)
return NULL;
to = (char *)binary_escape((unsigned char*)buffer, (size_t) buffer_len, to = (char *)binary_escape((unsigned char*)buffer, (size_t) buffer_len,
&len, self->conn ? ((connectionObject*)self->conn)->pgconn : NULL); &len, self->conn ? ((connectionObject*)self->conn)->pgconn : NULL);

View File

@ -63,11 +63,15 @@ class TypesBasicTests(unittest.TestCase):
def testBinary(self): def testBinary(self):
s = ''.join([chr(x) for x in range(256)]) s = ''.join([chr(x) for x in range(256)])
b = psycopg2.Binary(s) b = psycopg2.Binary(s)
r = str(self.execute("SELECT %s::bytea AS foo", (b,))) buf = self.execute("SELECT %s::bytea AS foo", (b,))
self.failUnless(r == s, "wrong binary quoting") self.failUnless(str(buf) == s, "wrong binary quoting")
# test to make sure an empty Binary is converted to an empty string # test to make sure an empty Binary is converted to an empty string
b = psycopg2.Binary('') b = psycopg2.Binary('')
self.assertEqual(str(b), "''") self.assertEqual(str(b), "''")
# test to make sure buffers returned by psycopg2 are
# understood by execute:
buf2 = self.execute("SELECT %s::bytea AS foo", (buf,))
self.failUnless(str(buf2) == s, "wrong binary quoting")
def testArray(self): def testArray(self):
s = self.execute("SELECT %s AS foo", ([[1,2],[3,4]],)) s = self.execute("SELECT %s AS foo", ([[1,2],[3,4]],))