Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
5b25f1d0
Commit
5b25f1d0
authored
Dec 05, 2018
by
Sergey Fedoseev
Committed by
Serhiy Storchaka
Dec 05, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-34052: Prevent SQLite functions from setting callbacks on exceptions. (GH-8113)
parent
f2f4555d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
84 additions
and
37 deletions
+84
-37
Lib/sqlite3/test/regression.py
Lib/sqlite3/test/regression.py
+64
-19
Misc/NEWS.d/next/Library/2018-07-24-16-37-40.bpo-34052.VbbFAE.rst
...S.d/next/Library/2018-07-24-16-37-40.bpo-34052.VbbFAE.rst
+7
-0
Modules/_sqlite/connection.c
Modules/_sqlite/connection.c
+13
-18
No files found.
Lib/sqlite3/test/regression.py
View file @
5b25f1d0
...
@@ -256,24 +256,6 @@ class RegressionTests(unittest.TestCase):
...
@@ -256,24 +256,6 @@ class RegressionTests(unittest.TestCase):
cur.execute("pragma page_size")
cur.execute("pragma page_size")
row = cur.fetchone()
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):
def CheckConnectionCall(self):
"""
"""
Call
a
connection
with
a
non
-
string
SQL
request
:
check
error
handling
Call
a
connection
with
a
non
-
string
SQL
request
:
check
error
handling
...
@@ -398,9 +380,72 @@ class RegressionTests(unittest.TestCase):
...
@@ -398,9 +380,72 @@ class RegressionTests(unittest.TestCase):
support
.
gc_collect
()
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
():
def
suite
():
regression_suite
=
unittest
.
makeSuite
(
RegressionTests
,
"Check"
)
regression_suite
=
unittest
.
makeSuite
(
RegressionTests
,
"Check"
)
return
unittest
.
TestSuite
((
regression_suite
,))
return
unittest
.
TestSuite
((
regression_suite
,
unittest
.
makeSuite
(
UnhashableCallbacksTestCase
),
))
def
test
():
def
test
():
runner
=
unittest
.
TextTestRunner
()
runner
=
unittest
.
TextTestRunner
()
...
...
Misc/NEWS.d/next/Library/2018-07-24-16-37-40.bpo-34052.VbbFAE.rst
0 → 100644
View file @
5b25f1d0
:meth:`sqlite3.Connection.create_aggregate`,
:meth:`sqlite3.Connection.create_function`,
:meth:`sqlite3.Connection.set_authorizer`,
:meth:`sqlite3.Connection.set_progress_handler` methods raises TypeError
when unhashable objects are passed as callable. These methods now don't pass
such objects to SQLite API. Previous behavior could lead to segfaults. Patch
by Sergey Fedoseev.
Modules/_sqlite/connection.c
View file @
5b25f1d0
...
@@ -843,7 +843,9 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec
...
@@ -843,7 +843,9 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec
flags
|=
SQLITE_DETERMINISTIC
;
flags
|=
SQLITE_DETERMINISTIC
;
#endif
#endif
}
}
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
func
,
Py_None
)
==
-
1
)
{
return
NULL
;
}
rc
=
sqlite3_create_function
(
self
->
db
,
rc
=
sqlite3_create_function
(
self
->
db
,
name
,
name
,
narg
,
narg
,
...
@@ -857,12 +859,8 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec
...
@@ -857,12 +859,8 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec
/* Workaround for SQLite bug: no error code or string is available here */
/* Workaround for SQLite bug: no error code or string is available here */
PyErr_SetString
(
pysqlite_OperationalError
,
"Error creating function"
);
PyErr_SetString
(
pysqlite_OperationalError
,
"Error creating function"
);
return
NULL
;
return
NULL
;
}
else
{
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
func
,
Py_None
)
==
-
1
)
return
NULL
;
Py_RETURN_NONE
;
}
}
Py_RETURN_NONE
;
}
}
PyObject
*
pysqlite_connection_create_aggregate
(
pysqlite_Connection
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
PyObject
*
pysqlite_connection_create_aggregate
(
pysqlite_Connection
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
...
@@ -883,17 +881,16 @@ PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObje
...
@@ -883,17 +881,16 @@ PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObje
return
NULL
;
return
NULL
;
}
}
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
aggregate_class
,
Py_None
)
==
-
1
)
{
return
NULL
;
}
rc
=
sqlite3_create_function
(
self
->
db
,
name
,
n_arg
,
SQLITE_UTF8
,
(
void
*
)
aggregate_class
,
0
,
&
_pysqlite_step_callback
,
&
_pysqlite_final_callback
);
rc
=
sqlite3_create_function
(
self
->
db
,
name
,
n_arg
,
SQLITE_UTF8
,
(
void
*
)
aggregate_class
,
0
,
&
_pysqlite_step_callback
,
&
_pysqlite_final_callback
);
if
(
rc
!=
SQLITE_OK
)
{
if
(
rc
!=
SQLITE_OK
)
{
/* Workaround for SQLite bug: no error code or string is available here */
/* Workaround for SQLite bug: no error code or string is available here */
PyErr_SetString
(
pysqlite_OperationalError
,
"Error creating aggregate"
);
PyErr_SetString
(
pysqlite_OperationalError
,
"Error creating aggregate"
);
return
NULL
;
return
NULL
;
}
else
{
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
aggregate_class
,
Py_None
)
==
-
1
)
return
NULL
;
Py_RETURN_NONE
;
}
}
Py_RETURN_NONE
;
}
}
static
int
_authorizer_callback
(
void
*
user_arg
,
int
action
,
const
char
*
arg1
,
const
char
*
arg2
,
const
char
*
dbname
,
const
char
*
access_attempt_source
)
static
int
_authorizer_callback
(
void
*
user_arg
,
int
action
,
const
char
*
arg1
,
const
char
*
arg2
,
const
char
*
dbname
,
const
char
*
access_attempt_source
)
...
@@ -1006,17 +1003,15 @@ static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, P
...
@@ -1006,17 +1003,15 @@ static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, P
return
NULL
;
return
NULL
;
}
}
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
authorizer_cb
,
Py_None
)
==
-
1
)
{
return
NULL
;
}
rc
=
sqlite3_set_authorizer
(
self
->
db
,
_authorizer_callback
,
(
void
*
)
authorizer_cb
);
rc
=
sqlite3_set_authorizer
(
self
->
db
,
_authorizer_callback
,
(
void
*
)
authorizer_cb
);
if
(
rc
!=
SQLITE_OK
)
{
if
(
rc
!=
SQLITE_OK
)
{
PyErr_SetString
(
pysqlite_OperationalError
,
"Error setting authorizer callback"
);
PyErr_SetString
(
pysqlite_OperationalError
,
"Error setting authorizer callback"
);
return
NULL
;
return
NULL
;
}
else
{
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
authorizer_cb
,
Py_None
)
==
-
1
)
return
NULL
;
Py_RETURN_NONE
;
}
}
Py_RETURN_NONE
;
}
}
static
PyObject
*
pysqlite_connection_set_progress_handler
(
pysqlite_Connection
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
static
PyObject
*
pysqlite_connection_set_progress_handler
(
pysqlite_Connection
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
...
@@ -1039,9 +1034,9 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s
...
@@ -1039,9 +1034,9 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s
/* None clears the progress handler previously set */
/* None clears the progress handler previously set */
sqlite3_progress_handler
(
self
->
db
,
0
,
0
,
(
void
*
)
0
);
sqlite3_progress_handler
(
self
->
db
,
0
,
0
,
(
void
*
)
0
);
}
else
{
}
else
{
sqlite3_progress_handler
(
self
->
db
,
n
,
_progress_handler
,
progress_handler
);
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
progress_handler
,
Py_None
)
==
-
1
)
if
(
PyDict_SetItem
(
self
->
function_pinboard
,
progress_handler
,
Py_None
)
==
-
1
)
return
NULL
;
return
NULL
;
sqlite3_progress_handler
(
self
->
db
,
n
,
_progress_handler
,
progress_handler
);
}
}
Py_RETURN_NONE
;
Py_RETURN_NONE
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment