]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-152912: Fix audit hook exception check in sys.addaudithook() (GH-152913)
authork00shi <265808442+k00shi@users.noreply.github.com>
Mon, 27 Jul 2026 19:35:40 +0000 (03:35 +0800)
committerGitHub <noreply@github.com>
Mon, 27 Jul 2026 19:35:40 +0000 (19:35 +0000)
Doc/c-api/sys.rst
Lib/test/audit-tests.py
Lib/test/test_audit.py
Misc/NEWS.d/next/Library/2026-07-03-02-11-00.gh-issue-152912.Mv3KpR.rst [new file with mode: 0644]
Python/sysmodule.c

index ee73c1c8adaa7b3a3c81b9f832c86e8a3e81866e..0a446f86e22eaf674bab106592a29af0a6cf9d75 100644 (file)
@@ -433,7 +433,7 @@ accessible to C code.  They all work with the current interpreter thread's
    This function is safe to call before :c:func:`Py_Initialize`. When called
    after runtime initialization, existing audit hooks are notified and may
    silently abort the operation by raising an error subclassed from
-   :class:`Exception` (other errors will not be silenced).
+   :class:`RuntimeError` (other errors will not be silenced).
 
    The hook function is always called with an :term:`attached thread state` by
    the Python interpreter that raised the event.
@@ -447,7 +447,7 @@ accessible to C code.  They all work with the current interpreter thread's
 
       If the interpreter is initialized, this function raises an auditing event
       ``sys.addaudithook`` with no arguments. If any existing hooks raise an
-      exception derived from :class:`Exception`, the new hook will not be
+      exception derived from :class:`RuntimeError`, the new hook will not be
       added and the exception is cleared. As a result, callers cannot assume
       that their hook has been added unless they control all existing hooks.
 
@@ -462,6 +462,11 @@ accessible to C code.  They all work with the current interpreter thread's
 
    .. versionadded:: 3.8
 
+   .. versionchanged:: 3.8.1
+
+      Exceptions derived from :class:`Exception` but not :class:`RuntimeError`
+      are no longer suppressed.
+
 
 .. _processcontrol:
 
index 8be5bf8aa4f5469270657c3e70be2ce483df8688..53bd369fabe21f7d473bdf20cacd8d14786bc4fa 100644 (file)
@@ -109,6 +109,16 @@ def test_block_add_hook_baseexception():
                 pass
 
 
+def test_block_add_hook_valueerror():
+    # Non-RuntimeError exceptions (like ValueError) should propagate out
+    with assertRaises(ValueError):
+        with TestHook(
+            raise_on_events="sys.addaudithook", exc_type=ValueError
+        ) as hook1:
+            with TestHook() as hook2:
+                pass
+
+
 def test_marshal():
     import marshal
     o = ("a", "b", "c", 1, 2, 3)
index db4e1eb9999c1fa43bbcab29fbf3e9de2ee44d89..e9e546fdbfd6fbe1be25dea16d5ae41a2de3eec7 100644 (file)
@@ -58,6 +58,9 @@ class AuditTest(unittest.TestCase):
     def test_block_add_hook_baseexception(self):
         self.do_test("test_block_add_hook_baseexception")
 
+    def test_block_add_hook_valueerror(self):
+        self.do_test("test_block_add_hook_valueerror")
+
     def test_marshal(self):
         import_helper.import_module("marshal")
 
diff --git a/Misc/NEWS.d/next/Library/2026-07-03-02-11-00.gh-issue-152912.Mv3KpR.rst b/Misc/NEWS.d/next/Library/2026-07-03-02-11-00.gh-issue-152912.Mv3KpR.rst
new file mode 100644 (file)
index 0000000..a4d7c4a
--- /dev/null
@@ -0,0 +1 @@
+``sys.addaudithook()`` now correctly suppresses only :exc:`RuntimeError` instead of all :exc:`Exception` subclasses when an existing audit hook raises during hook registration. Patch by Yeongu Kim.
index 9442472b53abbe1d8d5659df107462c871cb98c2..1e6e914b066bc5cf91729552d128a5c1da552da7 100644 (file)
@@ -527,8 +527,8 @@ sys_addaudithook_impl(PyObject *module, PyObject *hook)
 
     /* Invoke existing audit hooks to allow them an opportunity to abort. */
     if (_PySys_Audit(tstate, "sys.addaudithook", NULL) < 0) {
-        if (_PyErr_ExceptionMatches(tstate, PyExc_Exception)) {
-            /* We do not report errors derived from Exception */
+        if (_PyErr_ExceptionMatches(tstate, PyExc_RuntimeError)) {
+            /* We do not report errors derived from RuntimeError */
             _PyErr_Clear(tstate);
             Py_RETURN_NONE;
         }