summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Ossman (ThinLinc team) <ossman@cendio.se>2024-02-28 01:39:08 (GMT)
committerGitHub <noreply@github.com>2024-02-28 01:39:08 (GMT)
commit5a1559d9493dd298a08c4be32b52295aa3eb89e5 (patch)
tree013e044debb168ed58b68e7c7d75aeec3a9ae626
parenta355f60b032306651ca27bc53bbb82eb5106ff71 (diff)
downloadcpython-5a1559d9493dd298a08c4be32b52295aa3eb89e5.zip
cpython-5a1559d9493dd298a08c4be32b52295aa3eb89e5.tar.gz
cpython-5a1559d9493dd298a08c4be32b52295aa3eb89e5.tar.bz2
gh-112997: Don't log arguments in asyncio unless debugging (#115667)
Nothing else in Python generally logs the contents of variables, so this can be very unexpected for developers and could leak sensitive information in to terminals and log files.
-rw-r--r--Lib/asyncio/events.py6
-rw-r--r--Lib/asyncio/format_helpers.py22
-rw-r--r--Lib/test/test_asyncio/test_events.py24
-rw-r--r--Misc/NEWS.d/next/Library/2024-02-19-16-53-48.gh-issue-112997.sYBXRZ.rst2
4 files changed, 42 insertions, 12 deletions
diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py
index 072a99f..6807493 100644
--- a/Lib/asyncio/events.py
+++ b/Lib/asyncio/events.py
@@ -54,7 +54,8 @@ class Handle:
info.append('cancelled')
if self._callback is not None:
info.append(format_helpers._format_callback_source(
- self._callback, self._args))
+ self._callback, self._args,
+ debug=self._loop.get_debug()))
if self._source_traceback:
frame = self._source_traceback[-1]
info.append(f'created at {frame[0]}:{frame[1]}')
@@ -90,7 +91,8 @@ class Handle:
raise
except BaseException as exc:
cb = format_helpers._format_callback_source(
- self._callback, self._args)
+ self._callback, self._args,
+ debug=self._loop.get_debug())
msg = f'Exception in callback {cb}'
context = {
'message': msg,
diff --git a/Lib/asyncio/format_helpers.py b/Lib/asyncio/format_helpers.py
index 27d11fd..93737b7 100644
--- a/Lib/asyncio/format_helpers.py
+++ b/Lib/asyncio/format_helpers.py
@@ -19,19 +19,26 @@ def _get_function_source(func):
return None
-def _format_callback_source(func, args):
- func_repr = _format_callback(func, args, None)
+def _format_callback_source(func, args, *, debug=False):
+ func_repr = _format_callback(func, args, None, debug=debug)
source = _get_function_source(func)
if source:
func_repr += f' at {source[0]}:{source[1]}'
return func_repr
-def _format_args_and_kwargs(args, kwargs):
+def _format_args_and_kwargs(args, kwargs, *, debug=False):
"""Format function arguments and keyword arguments.
Special case for a single parameter: ('hello',) is formatted as ('hello').
+
+ Note that this function only returns argument details when
+ debug=True is specified, as arguments may contain sensitive
+ information.
"""
+ if not debug:
+ return '()'
+
# use reprlib to limit the length of the output
items = []
if args:
@@ -41,10 +48,11 @@ def _format_args_and_kwargs(args, kwargs):
return '({})'.format(', '.join(items))
-def _format_callback(func, args, kwargs, suffix=''):
+def _format_callback(func, args, kwargs, *, debug=False, suffix=''):
if isinstance(func, functools.partial):
- suffix = _format_args_and_kwargs(args, kwargs) + suffix
- return _format_callback(func.func, func.args, func.keywords, suffix)
+ suffix = _format_args_and_kwargs(args, kwargs, debug=debug) + suffix
+ return _format_callback(func.func, func.args, func.keywords,
+ debug=debug, suffix=suffix)
if hasattr(func, '__qualname__') and func.__qualname__:
func_repr = func.__qualname__
@@ -53,7 +61,7 @@ def _format_callback(func, args, kwargs, suffix=''):
else:
func_repr = repr(func)
- func_repr += _format_args_and_kwargs(args, kwargs)
+ func_repr += _format_args_and_kwargs(args, kwargs, debug=debug)
if suffix:
func_repr += suffix
return func_repr
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index c92c88b..5b9c871 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -2250,7 +2250,7 @@ class HandleTests(test_utils.TestCase):
h = asyncio.Handle(noop, (1, 2), self.loop)
filename, lineno = test_utils.get_function_source(noop)
self.assertEqual(repr(h),
- '<Handle noop(1, 2) at %s:%s>'
+ '<Handle noop() at %s:%s>'
% (filename, lineno))
# cancelled handle
@@ -2268,14 +2268,14 @@ class HandleTests(test_utils.TestCase):
# partial function
cb = functools.partial(noop, 1, 2)
h = asyncio.Handle(cb, (3,), self.loop)
- regex = (r'^<Handle noop\(1, 2\)\(3\) at %s:%s>$'
+ regex = (r'^<Handle noop\(\)\(\) at %s:%s>$'
% (re.escape(filename), lineno))
self.assertRegex(repr(h), regex)
# partial function with keyword args
cb = functools.partial(noop, x=1)
h = asyncio.Handle(cb, (2, 3), self.loop)
- regex = (r'^<Handle noop\(x=1\)\(2, 3\) at %s:%s>$'
+ regex = (r'^<Handle noop\(\)\(\) at %s:%s>$'
% (re.escape(filename), lineno))
self.assertRegex(repr(h), regex)
@@ -2316,6 +2316,24 @@ class HandleTests(test_utils.TestCase):
'<Handle cancelled noop(1, 2) at %s:%s created at %s:%s>'
% (filename, lineno, create_filename, create_lineno))
+ # partial function
+ cb = functools.partial(noop, 1, 2)
+ create_lineno = sys._getframe().f_lineno + 1
+ h = asyncio.Handle(cb, (3,), self.loop)
+ regex = (r'^<Handle noop\(1, 2\)\(3\) at %s:%s created at %s:%s>$'
+ % (re.escape(filename), lineno,
+ re.escape(create_filename), create_lineno))
+ self.assertRegex(repr(h), regex)
+
+ # partial function with keyword args
+ cb = functools.partial(noop, x=1)
+ create_lineno = sys._getframe().f_lineno + 1
+ h = asyncio.Handle(cb, (2, 3), self.loop)
+ regex = (r'^<Handle noop\(x=1\)\(2, 3\) at %s:%s created at %s:%s>$'
+ % (re.escape(filename), lineno,
+ re.escape(create_filename), create_lineno))
+ self.assertRegex(repr(h), regex)
+
def test_handle_source_traceback(self):
loop = asyncio.get_event_loop_policy().new_event_loop()
loop.set_debug(True)
diff --git a/Misc/NEWS.d/next/Library/2024-02-19-16-53-48.gh-issue-112997.sYBXRZ.rst b/Misc/NEWS.d/next/Library/2024-02-19-16-53-48.gh-issue-112997.sYBXRZ.rst
new file mode 100644
index 0000000..4f97b2d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-02-19-16-53-48.gh-issue-112997.sYBXRZ.rst
@@ -0,0 +1,2 @@
+Stop logging potentially sensitive callback arguments in :mod:`asyncio`
+unless debug mode is active.