Skip to content

Commit 46a02db

Browse files
author
Yury Selivanov
committed
Issue #28653: Fix a refleak in functools.lru_cache.
1 parent 28f42fd commit 46a02db

3 files changed

Lines changed: 27 additions & 2 deletions

File tree

Lib/test/test_functools.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,25 @@ def f(x):
11621162
self.assertEqual(misses, 4)
11631163
self.assertEqual(currsize, 2)
11641164

1165+
def test_lru_type_error(self):
1166+
# Regression test for issue #28653.
1167+
# lru_cache was leaking when one of the arguments
1168+
# wasn't cacheable.
1169+
1170+
@functools.lru_cache(maxsize=None)
1171+
def infinite_cache(o):
1172+
pass
1173+
1174+
@functools.lru_cache(maxsize=10)
1175+
def limited_cache(o):
1176+
pass
1177+
1178+
with self.assertRaises(TypeError):
1179+
infinite_cache([])
1180+
1181+
with self.assertRaises(TypeError):
1182+
limited_cache([])
1183+
11651184
def test_lru_with_maxsize_none(self):
11661185
@self.module.lru_cache(maxsize=None)
11671186
def fib(n):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ Library
457457

458458
- Issue #28652: Make loop methods reject socket kinds they do not support.
459459

460+
- Issue #28653: Fix a refleak in functools.lru_cache.
461+
460462
IDLE
461463
----
462464

Modules/_functoolsmodule.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,10 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd
781781
if (!key)
782782
return NULL;
783783
hash = PyObject_Hash(key);
784-
if (hash == -1)
784+
if (hash == -1) {
785+
Py_DECREF(key);
785786
return NULL;
787+
}
786788
result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
787789
if (result) {
788790
Py_INCREF(result);
@@ -837,8 +839,10 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
837839
if (!key)
838840
return NULL;
839841
hash = PyObject_Hash(key);
840-
if (hash == -1)
842+
if (hash == -1) {
843+
Py_DECREF(key);
841844
return NULL;
845+
}
842846
link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
843847
if (link) {
844848
lru_cache_extricate_link(link);

0 commit comments

Comments
 (0)