[Python-checkins] bpo-43132: Fix incorrect handling of PyObject_RichCompareBool() in _zoneinfo (GH-24450) (GH-24457)

serhiy-storchaka webhook-mailer at python.org
Fri Feb 5 12:14:12 EST 2021


https://github.com/python/cpython/commit/c8b4375fe1aca1188f57ecf482547abd77e3ef91
commit: c8b4375fe1aca1188f57ecf482547abd77e3ef91
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: serhiy-storchaka <storchaka at gmail.com>
date: 2021-02-05T19:13:40+02:00
summary:

bpo-43132: Fix incorrect handling of PyObject_RichCompareBool() in _zoneinfo (GH-24450) (GH-24457)

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.
(cherry picked from commit effaec0bb54f381db8ccfa62514bc26b00946b40)

Co-authored-by: Zackery Spytz <zspytz at gmail.com>

files:
M Modules/_zoneinfo.c

diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index 0a4b38a6dc5ad..f655768496e13 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -163,7 +163,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);
@@ -265,7 +265,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;
     }
 
@@ -428,7 +428,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,
@@ -2347,7 +2350,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;
         }
 
@@ -2361,11 +2368,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);
@@ -2374,6 +2381,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.



More information about the Python-checkins mailing list