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.
This commit is contained in:
Zackery Spytz 2021-02-05 01:25:30 -07:00 committed by GitHub
parent 755c6e637a
commit effaec0bb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -164,7 +164,7 @@ is_leap_year(int year);
static size_t static size_t
_bisect(const int64_t value, const int64_t *arr, size_t size); _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); eject_from_strong_cache(const PyTypeObject *const type, PyObject *key);
static void static void
clear_strong_cache(const PyTypeObject *const type); 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); PyObject *instance = zone_from_strong_cache(type, key);
if (instance != NULL) { if (instance != NULL || PyErr_Occurred()) {
return instance; return instance;
} }
@ -429,7 +429,10 @@ zoneinfo_clear_cache(PyObject *cls, PyObject *args, PyObject *kwargs)
while ((item = PyIter_Next(iter))) { while ((item = PyIter_Next(iter))) {
// Remove from strong cache // 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 // Remove from weak cache
PyObject *tmp = PyObject_CallMethodObjArgs(weak_cache, pop, item, 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; const StrongCacheNode *node = root;
while (node != NULL) { 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; 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. * 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) eject_from_strong_cache(const PyTypeObject *const type, PyObject *key)
{ {
if (type != &PyZoneInfo_ZoneInfoType) { if (type != &PyZoneInfo_ZoneInfoType) {
return; return 0;
} }
StrongCacheNode *node = find_in_strong_cache(ZONEINFO_STRONG_CACHE, key); 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); strong_cache_node_free(node);
} }
else if (PyErr_Occurred()) {
return -1;
}
return 0;
} }
/* Moves a node to the front of the LRU cache. /* Moves a node to the front of the LRU cache.