8000 bpo-43762: Add audit events for loading of sqlite3 extensions (GH-25246) · python/cpython@7244c00 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7244c00

Browse files
author
Erlend Egeberg Aasland
authored
bpo-43762: Add audit events for loading of sqlite3 extensions (GH-25246)
1 parent 52cd6d5 commit 7244c00

File tree

7 files changed

+86
-0
lines changed

7 files changed

+86
-0
lines changed

Doc/library/sqlite3.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,17 @@ Module functions and constants
225225
be found in the `SQLite URI documentation <https://www.sqlite.org/uri.html>`_.
226226

227227
.. audit-event:: sqlite3.connect database sqlite3.connect
228+
.. audit-event:: sqlite3.connect/handle connection_handle sqlite3.connect
228229

229230
.. versionchanged:: 3.4
230231
Added the *uri* parameter.
231232

232233
.. versionchanged:: 3.7
233234
*database* can now also be a :term:`path-like object`, not only a string.
234235

236+
.. versionchanged:: 3.10
237+
Added the ``sqlite3.connect/handle`` auditing event.
238+
235239

236240
.. function:: register_converter(typename, callable)
237241

@@ -467,8 +471,13 @@ Connection Objects
467471

468472
Loadable extensions are disabled by default. See [#f1]_.
469473

474+
.. audit-event:: sqlite3.enable_load_extension connection,enabled sqlite3.enable_load_extension
475+
470476
.. versionadded:: 3.2
471477

478+
.. versionchanged:: 3.10
479+
Added the ``sqlite3.enable_load_extension`` auditing event.
480+
472481
.. literalinclude:: ../includes/sqlite3/load_extension.py
473482

474483
.. method:: load_extension(path)
@@ -479,8 +488,13 @@ Connection Objects
479488

480489
Loadable extensions are disabled by default. See [#f1]_.
481490

491+
.. audit-event:: sqlite3.load_extension connection,path sqlite3.load_extension
492+
482493
.. versionadded:: 3.2
483494

495+
.. versionchanged:: 3.10
496+
Added the ``sqlite3.load_extension`` auditing event.
497+
484498
.. attribute:: row_factory
485499

486500
You can change this attribute to a callable that accepts the cursor and the

Doc/whatsnew/3.10.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,14 @@ ssl
10801080
Add a *timeout* parameter to the :func:`ssl.get_server_certificate` function.
10811081
(Contributed by Zackery Spytz in :issue:`31870`.)
10821082
1083+
sqlite3
1084+
-------
1085+
1086+
Add audit events for :func:`~sqlite3.connect/handle`,
1087+
:meth:`~sqlite3.Connection.enable_load_extension`, and
1088+
:meth:`~sqlite3.Connection.load_extension`.
1089+
(Contributed by Erlend E. Aasland in :issue:`43762`.)
1090+
10831091
sys
10841092
---
10851093

Lib/test/audit-tests.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,27 @@ def hook(event, args):
359359
conn.close()
360360

361361

362+
def test_sqlite3():
363+
import sqlite3
364+
365+
def hook(event, *args):
366+
if event.startswith("sqlite3."):
367+
print(event, *args)
368+
369+
sys.addaudithook(hook)
370+
cx = sqlite3.connect(":memory:")
371+
372+
# Configured without --enable-loadable-sqlite-extensions
373+
if hasattr(sqlite3.Connection, "enable_load_extension"):
374+
cx.enable_load_extension(False)
375+
try:
376+
cx.load_extension("test")
377+
except sqlite3.OperationalError:
378+
pass
379+
else:
380+
raise RuntimeError("Expected sqlite3.load_extension to fail")
381+
382+
362383
if __name__ == "__main__":
363384
from test.support import suppress_msvcrt_asserts
364385

Lib/test/test_audit.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def test_gc(self):
130130
["gc.get_objects", "gc.get_referrers", "gc.get_referents"]
131131
)
132132

133+
133134
def test_http(self):
134135
import_helper.import_module("http.client")
135136
returncode, events, stderr = self.run_python("test_http_client")
@@ -145,5 +146,27 @@ def test_http(self):
145146
self.assertIn('HTTP', events[1][2])
146147

147148

149+
def test_sqlite3(self):
150+
try:
151+
import sqlite3
152+
except ImportError:
153+
return
154+
returncode, events, stderr = self.run_python("test_sqlite3")
155+
if returncode:
156+
self.fail(stderr)
157+
158+
if support.verbose:
159+
print(*events, sep='\n')
160+
actual = [ev[0] for ev in events]
161+
expected = ["sqlite3.connect", "sqlite3.connect/handle"]
162+
163+
if hasattr(sqlite3.Connection, "enable_load_extension"):
164+
expected += [
165+
"sqlite3.enable_load_extension",
166+
"sqlite3.load_extension",
167+
]
168+
self.assertEqual(actual, expected)
169+
170+
148171
if __name__ == "__main__":
149172
unittest.main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add audit events for :func:`sqlite3.connect/handle`,
2+
:meth:`sqlite3.Connection.enable_load_extension`, and
3+
:meth:`sqlite3.Connection.load_extension`. Patch by Erlend E. Aasland.

Modules/_sqlite/connection.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,11 @@ pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self,
11541154
{
11551155
int rc;
11561156

1157+
if (PySys_Audit("sqlite3.enable_load_extension",
1158+
"OO", self, onoff ? Py_True : Py_False) < 0) {
1159+
return NULL;
1160+
}
1161+
11571162
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
11581163
return NULL;
11591164
}
@@ -1185,6 +1190,10 @@ pysqlite_connection_load_extension_impl(pysqlite_Connection *self,
11851190
int rc;
11861191
char* errmsg;
11871192

1193+
if (PySys_Audit("sqlite3.load_extension", "Os", self, extension_name) < 0) {
1194+
return NULL;
1195+
}
1196+
11881197
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
11891198
return NULL;
11901199
}

Modules/_sqlite/module.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
9696
}
9797

9898
result = PyObject_Call(factory, args, kwargs);
99+
if (result == NULL) {
100+
return NULL;
101+
}
102+
103+
if (PySys_Audit("sqlite3.connect/handle", "O", self) < 0) {
104+
Py_DECREF(result);
105+
return NULL;
106+
}
99107

100108
return result;
101109
}

0 commit comments

Comments
 (0)
0