summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2018-12-05 17:50:26 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2018-12-05 17:50:26 (GMT)
commit5b25f1d03100e2283c1b129d461ba68ac0169a14 (patch)
tree071d15ff6170a1180a57e35ee703b6b27e6d0046 /Lib
parentf2f4555d8287ad217a1dba7bbd93103ad4daf3a8 (diff)
downloadcpython-5b25f1d03100e2283c1b129d461ba68ac0169a14.zip
cpython-5b25f1d03100e2283c1b129d461ba68ac0169a14.tar.gz
cpython-5b25f1d03100e2283c1b129d461ba68ac0169a14.tar.bz2
bpo-34052: Prevent SQLite functions from setting callbacks on exceptions. (GH-8113)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/sqlite3/test/regression.py83
1 files changed, 64 insertions, 19 deletions
diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py
index 34cd233..1c59a3c 100644
--- a/Lib/sqlite3/test/regression.py
+++ b/Lib/sqlite3/test/regression.py
@@ -256,24 +256,6 @@ class RegressionTests(unittest.TestCase):
cur.execute("pragma page_size")
row = cur.fetchone()
- def CheckSetDict(self):
- """
- See http://bugs.python.org/issue7478
-
- It was possible to successfully register callbacks that could not be
- hashed. Return codes of PyDict_SetItem were not checked properly.
- """
- class NotHashable:
- def __call__(self, *args, **kw):
- pass
- def __hash__(self):
- raise TypeError()
- var = NotHashable()
- self.assertRaises(TypeError, self.con.create_function, var)
- self.assertRaises(TypeError, self.con.create_aggregate, var)
- self.assertRaises(TypeError, self.con.set_authorizer, var)
- self.assertRaises(TypeError, self.con.set_progress_handler, var)
-
def CheckConnectionCall(self):
"""
Call a connection with a non-string SQL request: check error handling
@@ -398,9 +380,72 @@ class RegressionTests(unittest.TestCase):
support.gc_collect()
+class UnhashableFunc:
+ __hash__ = None
+
+ def __init__(self, return_value=None):
+ self.calls = 0
+ self.return_value = return_value
+
+ def __call__(self, *args, **kwargs):
+ self.calls += 1
+ return self.return_value
+
+
+class UnhashableCallbacksTestCase(unittest.TestCase):
+ """
+ https://bugs.python.org/issue34052
+
+ Registering unhashable callbacks raises TypeError, callbacks are not
+ registered in SQLite after such registration attempt.
+ """
+ def setUp(self):
+ self.con = sqlite.connect(':memory:')
+
+ def tearDown(self):
+ self.con.close()
+
+ def test_progress_handler(self):
+ f = UnhashableFunc(return_value=0)
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ self.con.set_progress_handler(f, 1)
+ self.con.execute('SELECT 1')
+ self.assertFalse(f.calls)
+
+ def test_func(self):
+ func_name = 'func_name'
+ f = UnhashableFunc()
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ self.con.create_function(func_name, 0, f)
+ msg = 'no such function: %s' % func_name
+ with self.assertRaisesRegex(sqlite.OperationalError, msg):
+ self.con.execute('SELECT %s()' % func_name)
+ self.assertFalse(f.calls)
+
+ def test_authorizer(self):
+ f = UnhashableFunc(return_value=sqlite.SQLITE_DENY)
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ self.con.set_authorizer(f)
+ self.con.execute('SELECT 1')
+ self.assertFalse(f.calls)
+
+ def test_aggr(self):
+ class UnhashableType(type):
+ __hash__ = None
+ aggr_name = 'aggr_name'
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ self.con.create_aggregate(aggr_name, 0, UnhashableType('Aggr', (), {}))
+ msg = 'no such function: %s' % aggr_name
+ with self.assertRaisesRegex(sqlite.OperationalError, msg):
+ self.con.execute('SELECT %s()' % aggr_name)
+
+
def suite():
regression_suite = unittest.makeSuite(RegressionTests, "Check")
- return unittest.TestSuite((regression_suite,))
+ return unittest.TestSuite((
+ regression_suite,
+ unittest.makeSuite(UnhashableCallbacksTestCase),
+ ))
def test():
runner = unittest.TextTestRunner()