From 2fed98553019df8d72355a90bb31c14c1309be79 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 24 Oct 2022 10:51:51 +0200 Subject: [PATCH 1/3] break potential reference cycles in external code worsened by typing.py lru_cache (#98253) --- Lib/typing.py | 9 ++++++--- .../2022-10-24-11-01-05.gh-issue-98253.HVd5v4.rst | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-10-24-11-01-05.gh-issue-98253.HVd5v4.rst diff --git a/Lib/typing.py b/Lib/typing.py index 95bd61c7f8c61f..be191555205aa1 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -344,6 +344,7 @@ def _flatten_literal_params(parameters): _cleanups = [] +_caches = { } def _tp_cache(func=None, /, *, typed=False): @@ -351,13 +352,15 @@ def _tp_cache(func=None, /, *, typed=False): original function for non-hashable arguments. """ def decorator(func): - cached = functools.lru_cache(typed=typed)(func) - _cleanups.append(cached.cache_clear) + cache = functools.lru_cache(typed=typed)(func) + _caches[func] = cache + _cleanups.append(cache.cache_clear) + del cache @functools.wraps(func) def inner(*args, **kwds): try: - return cached(*args, **kwds) + return _caches[func](*args, **kwds) except TypeError: pass # All real errors (not unhashable args) are raised below. return func(*args, **kwds) diff --git a/Misc/NEWS.d/next/Library/2022-10-24-11-01-05.gh-issue-98253.HVd5v4.rst b/Misc/NEWS.d/next/Library/2022-10-24-11-01-05.gh-issue-98253.HVd5v4.rst new file mode 100644 index 00000000000000..00df0070f3b9c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-10-24-11-01-05.gh-issue-98253.HVd5v4.rst @@ -0,0 +1,10 @@ +The implementation of the typing module is now more resilient to reference +leaks in binary extension modules. + +Previously, a reference leak in a typed C API-based extension module could leak +internals of the typing module, which could in turn introduce leaks in +essentially any other package with typed function signatures. Although the +typing package is not the original source of the problem, such non-local +dependences exacerbate debugging of large-scale projects, and the +implementation was therefore changed to reduce harm by providing better +isolation. From 411fd55cb86c1cf4befe634e7363dea9599e54ac Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 25 Nov 2022 16:01:20 +0100 Subject: [PATCH 2/3] added a comment clarifying the indirection --- Lib/typing.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/typing.py b/Lib/typing.py index be191555205aa1..3b1a242f96d3bf 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -352,6 +352,11 @@ def _tp_cache(func=None, /, *, typed=False): original function for non-hashable arguments. """ def decorator(func): + # The callback 'inner' references the newly created lru_cache + # indirectly by performing a lookup in the global '_caches' dictionary. + # This breaks a reference that can be problematic when combined with + # C API extensions that leak references to types. See GH-98253. + cache = functools.lru_cache(typed=typed)(func) _caches[func] = cache _cleanups.append(cache.cache_clear) From f27e49d72419511e0b84279ff85a86312e574f35 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 25 Nov 2022 16:02:03 +0100 Subject: [PATCH 3/3] removed superfluous space --- Lib/typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/typing.py b/Lib/typing.py index 3b1a242f96d3bf..350a827a2ebfba 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -344,7 +344,7 @@ def _flatten_literal_params(parameters): _cleanups = [] -_caches = { } +_caches = {} def _tp_cache(func=None, /, *, typed=False): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy