aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZackery Spytz <zspytz@gmail.com>2021-02-05 01:25:30 -0700
committerGitHub <noreply@github.com>2021-02-05 10:25:30 +0200
commiteffaec0bb54f381db8ccfa62514bc26b00946b40 (patch)
tree19073d9df8fc11ca4823ef321b33edb0ac6dab38
parentMinor readability improvements. Also note performance impact of __slots__. (... (diff)
downloadcpython-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.c23
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.