diff options
author | 2021-02-05 01:25:30 -0700 | |
---|---|---|
committer | 2021-02-05 10:25:30 +0200 | |
commit | effaec0bb54f381db8ccfa62514bc26b00946b40 (patch) | |
tree | 19073d9df8fc11ca4823ef321b33edb0ac6dab38 | |
parent | Minor readability improvements. Also note performance impact of __slots__. (... (diff) | |
download | cpython-effaec0bb54f381db8ccfa62514bc26b00946b40.tar.gz cpython-effaec0bb54f381db8ccfa62514bc26b00946b40.tar.bz2 cpython-effaec0bb54f381db8ccfa62514bc26b00946b40.zip |
bpo-43132: Fix incorrect handling of PyObject_RichCompareBool() in _zoneinfo (GH-24450)
PyObject_RichCompareBool() returns -1 on error, but this case is
not handled by the find_in_strong_cache() function. Any exception
raised by PyObject_RichCompareBool() should be propagated.
-rw-r--r-- | Modules/_zoneinfo.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index d0c462fb86..4726b82b6a 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -164,7 +164,7 @@ is_leap_year(int year); static size_t _bisect(const int64_t value, const int64_t *arr, size_t size); -static void +static int eject_from_strong_cache(const PyTypeObject *const type, PyObject *key); static void clear_strong_cache(const PyTypeObject *const type); @@ -266,7 +266,7 @@ zoneinfo_new(PyTypeObject *type, PyObject *args, PyObject *kw) } PyObject *instance = zone_from_strong_cache(type, key); - if (instance != NULL) { + if (instance != NULL || PyErr_Occurred()) { return instance; } @@ -429,7 +429,10 @@ zoneinfo_clear_cache(PyObject *cls, PyObject *args, PyObject *kwargs) while ((item = PyIter_Next(iter))) { // Remove from strong cache - eject_from_strong_cache(type, item); + if (eject_from_strong_cache(type, item) < 0) { + Py_DECREF(item); + break; + } // Remove from weak cache PyObject *tmp = PyObject_CallMethodObjArgs(weak_cache, pop, item, @@ -2342,7 +2345,11 @@ find_in_strong_cache(const StrongCacheNode *const root, PyObject *const key) { const StrongCacheNode *node = root; while (node != NULL) { - if (PyObject_RichCompareBool(key, node->key, Py_EQ)) { + int rv = PyObject_RichCompareBool(key, node->key, Py_EQ); + if (rv < 0) { + return NULL; + } + if (rv) { return (StrongCacheNode *)node; } @@ -2356,11 +2363,11 @@ find_in_strong_cache(const StrongCacheNode *const root, PyObject *const key) * * This function is used to enable the per-key functionality in clear_cache. */ -static void +static int eject_from_strong_cache(const PyTypeObject *const type, PyObject *key) { if (type != &PyZoneInfo_ZoneInfoType) { - return; + return 0; } StrongCacheNode *node = find_in_strong_cache(ZONEINFO_STRONG_CACHE, key); @@ -2369,6 +2376,10 @@ eject_from_strong_cache(const PyTypeObject *const type, PyObject *key) strong_cache_node_free(node); } + else if (PyErr_Occurred()) { + return -1; + } + return 0; } /* Moves a node to the front of the LRU cache. |