bpo-38175: Fix a memory leak in comparison of sqlite3.Row objects. (GH-16155)

(cherry picked from commit 8debfa5040)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Miss Islington (bot) 2019-09-16 23:14:30 -07:00 committed by GitHub
parent 89f132a328
commit 4ac1be2828
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 12 deletions

View File

@ -169,19 +169,33 @@ class RowFactoryTests(unittest.TestCase):
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone() row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone() row_2 = self.con.execute("select 1 as a, 2 as b").fetchone()
row_3 = self.con.execute("select 1 as a, 3 as b").fetchone() row_3 = self.con.execute("select 1 as a, 3 as b").fetchone()
row_4 = self.con.execute("select 1 as b, 2 as a").fetchone()
row_5 = self.con.execute("select 2 as b, 1 as a").fetchone()
self.assertEqual(row_1, row_1) self.assertTrue(row_1 == row_1)
self.assertEqual(row_1, row_2) self.assertTrue(row_1 == row_2)
self.assertTrue(row_2 != row_3) self.assertFalse(row_1 == row_3)
self.assertFalse(row_1 == row_4)
self.assertFalse(row_1 == row_5)
self.assertFalse(row_1 == object())
self.assertFalse(row_1 != row_1) self.assertFalse(row_1 != row_1)
self.assertFalse(row_1 != row_2) self.assertFalse(row_1 != row_2)
self.assertFalse(row_2 == row_3) self.assertTrue(row_1 != row_3)
self.assertTrue(row_1 != row_4)
self.assertTrue(row_1 != row_5)
self.assertTrue(row_1 != object())
with self.assertRaises(TypeError):
row_1 > row_2
with self.assertRaises(TypeError):
row_1 < row_2
with self.assertRaises(TypeError):
row_1 >= row_2
with self.assertRaises(TypeError):
row_1 <= row_2
self.assertEqual(row_1, row_2)
self.assertEqual(hash(row_1), hash(row_2)) self.assertEqual(hash(row_1), hash(row_2))
self.assertNotEqual(row_1, row_3)
self.assertNotEqual(hash(row_1), hash(row_3))
def CheckSqliteRowAsSequence(self): def CheckSqliteRowAsSequence(self):
""" Checks if the row object can act like a sequence """ """ Checks if the row object can act like a sequence """

View File

@ -0,0 +1 @@
Fix a memory leak in comparison of :class:`sqlite3.Row` objects.

View File

@ -197,14 +197,16 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
if (opid != Py_EQ && opid != Py_NE) if (opid != Py_EQ && opid != Py_NE)
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other; pysqlite_Row *other = (pysqlite_Row *)_other;
PyObject *res = PyObject_RichCompare(self->description, other->description, opid); int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
if ((opid == Py_EQ && res == Py_True) if (eq < 0) {
|| (opid == Py_NE && res == Py_False)) { return NULL;
Py_DECREF(res); }
if (eq) {
return PyObject_RichCompare(self->data, other->data, opid); return PyObject_RichCompare(self->data, other->data, opid);
} }
return PyBool_FromLong(opid != Py_EQ);
} }
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
} }