Skip to content

Commit 8debfa5

Browse files
bpo-38175: Fix a memory leak in comparison of sqlite3.Row objects. (GH-16155)
1 parent a9187c3 commit 8debfa5

File tree

3 files changed

+29
-12
lines changed

3 files changed

+29
-12
lines changed

Lib/sqlite3/test/factory.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,19 +169,33 @@ def CheckSqliteRowHashCmp(self):
169169
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
170170
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone()
171171
row_3 = self.con.execute("select 1 as a, 3 as b").fetchone()
172+
row_4 = self.con.execute("select 1 as b, 2 as a").fetchone()
173+
row_5 = self.con.execute("select 2 as b, 1 as a").fetchone()
172174

173-
self.assertEqual(row_1, row_1)
174-
self.assertEqual(row_1, row_2)
175-
self.assertTrue(row_2 != row_3)
175+
self.assertTrue(row_1 == row_1)
176+
self.assertTrue(row_1 == row_2)
177+
self.assertFalse(row_1 == row_3)
178+
self.assertFalse(row_1 == row_4)
179+
self.assertFalse(row_1 == row_5)
180+
self.assertFalse(row_1 == object())
176181

177182
self.assertFalse(row_1 != row_1)
178183
self.assertFalse(row_1 != row_2)
179-
self.assertFalse(row_2 == row_3)
184+
self.assertTrue(row_1 != row_3)
185+
self.assertTrue(row_1 != row_4)
186+
self.assertTrue(row_1 != row_5)
187+
self.assertTrue(row_1 != object())
188+
189+
with self.assertRaises(TypeError):
190+
row_1 > row_2
191+
with self.assertRaises(TypeError):
192+
row_1 < row_2
193+
with self.assertRaises(TypeError):
194+
row_1 >= row_2
195+
with self.assertRaises(TypeError):
196+
row_1 <= row_2
180197

181-
self.assertEqual(row_1, row_2)
182198
self.assertEqual(hash(row_1), hash(row_2))
183-
self.assertNotEqual(row_1, row_3)
184-
self.assertNotEqual(hash(row_1), hash(row_3))
185199

186200
def CheckSqliteRowAsSequence(self):
187201
""" Checks if the row object can act like a sequence """
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a memory leak in comparison of :class:`sqlite3.Row` objects.

Modules/_sqlite/row.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,16 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
192192
if (opid != Py_EQ && opid != Py_NE)
193193
Py_RETURN_NOTIMPLEMENTED;
194194

195-
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
195+
if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
196196
pysqlite_Row *other = (pysqlite_Row *)_other;
197-
PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
198-
if ((opid == Py_EQ && res == Py_True)
199-
|| (opid == Py_NE && res == Py_False)) {
200-
Py_DECREF(res);
197+
int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
198+
if (eq < 0) {
199+
return NULL;
200+
}
201+
if (eq) {
201202
return PyObject_RichCompare(self->data, other->data, opid);
202203
}
204+
return PyBool_FromLong(opid != Py_EQ);
203205
}
204206
Py_RETURN_NOTIMPLEMENTED;
205207
}

0 commit comments

Comments
 (0)