diff options
author | Pierre Ossman (ThinLinc team) <ossman@cendio.se> | 2024-02-28 01:39:08 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-28 01:39:08 (GMT) |
commit | 5a1559d9493dd298a08c4be32b52295aa3eb89e5 (patch) | |
tree | 013e044debb168ed58b68e7c7d75aeec3a9ae626 /Lib | |
parent | a355f60b032306651ca27bc53bbb82eb5106ff71 (diff) | |
download | cpython-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.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/asyncio/events.py | 6 | ||||
-rw-r--r-- | Lib/asyncio/format_helpers.py | 22 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 24 |
3 files changed, 40 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) |