summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-09-17 09:56:27 +0300
committerGitHub <noreply@github.com>2019-09-17 09:56:27 +0300
commitbe257bcad12b1d72a2c2a8199d2291ae22bccf78 (patch)
tree3fd63f1fa65acf8068a06bae2c3acf6a74b39431
parent5d55d52b61f56522e616ac1423437d4e3f641ce6 (diff)
downloadcpython-git-be257bcad12b1d72a2c2a8199d2291ae22bccf78.tar.gz
[2.7] bpo-38175: Fix a memory leak in comparison of sqlite3.Row objects. (GH-16155). (GH-16215)
(cherry picked from commit 8debfa50407107ff2329d01081cdc12d359f1d12)
-rw-r--r--Lib/sqlite3/test/factory.py19
-rw-r--r--Misc/NEWS.d/next/Library/2019-09-15-10-30-33.bpo-38175.61XlUv.rst1
-rw-r--r--Modules/_sqlite/row.c12
3 files changed, 20 insertions, 12 deletions
diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py
index b9e9cd7fd7..b8e0f645a0 100644
--- a/Lib/sqlite3/test/factory.py
+++ b/Lib/sqlite3/test/factory.py
@@ -159,19 +159,24 @@ class RowFactoryTests(unittest.TestCase):
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_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.assertEqual(row_1, row_2)
- self.assertTrue(row_2 != row_3)
+ self.assertTrue(row_1 == row_1)
+ self.assertTrue(row_1 == row_2)
+ 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_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())
- self.assertEqual(row_1, 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):
""" Checks if the row object can act like a sequence """
diff --git a/Misc/NEWS.d/next/Library/2019-09-15-10-30-33.bpo-38175.61XlUv.rst b/Misc/NEWS.d/next/Library/2019-09-15-10-30-33.bpo-38175.61XlUv.rst
new file mode 100644
index 0000000000..6d9f280bbd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-09-15-10-30-33.bpo-38175.61XlUv.rst
@@ -0,0 +1 @@
+Fix a memory leak in comparison of :class:`sqlite3.Row` objects.
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c
index 9ebe7b7b81..c0da329c13 100644
--- a/Modules/_sqlite/row.c
+++ b/Modules/_sqlite/row.c
@@ -199,14 +199,16 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
- if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
+ if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other;
- PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
- if ((opid == Py_EQ && res == Py_True)
- || (opid == Py_NE && res == Py_False)) {
- Py_DECREF(res);
+ int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
+ if (eq < 0) {
+ return NULL;
+ }
+ if (eq) {
return PyObject_RichCompare(self->data, other->data, opid);
}
+ return PyBool_FromLong(opid != Py_EQ);
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;