]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111178: fix UBSan failures in `Modules/_zoneinfo.c` (GH-129798)
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Wed, 26 Feb 2025 08:36:59 +0000 (09:36 +0100)
committerGitHub <noreply@github.com>
Wed, 26 Feb 2025 08:36:59 +0000 (09:36 +0100)
Fix UBSan failures for `PyZoneInfo_ZoneInfo`

Fix semantic naming

Modules/_zoneinfo.c

index 1fcea9ce8b126176b7b4610e706b1c13f8605b20..8c882bef24867ecd75ef5b7d63376676766d92d3 100644 (file)
@@ -56,6 +56,8 @@ typedef struct {
     unsigned char source;
 } PyZoneInfo_ZoneInfo;
 
+#define PyZoneInfo_ZoneInfo_CAST(op)    ((PyZoneInfo_ZoneInfo *)(op))
+
 struct TransitionRuleType {
     int64_t (*year_to_timestamp)(TransitionRuleType *, int);
 };
@@ -238,7 +240,7 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
         }
     }
 
-    PyObject *self = (PyObject *)(type->tp_alloc(type, 0));
+    PyObject *self = type->tp_alloc(type, 0);
     if (self == NULL) {
         goto error;
     }
@@ -251,7 +253,8 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
         }
     }
 
-    if (load_data(state, (PyZoneInfo_ZoneInfo *)self, file_obj)) {
+    PyZoneInfo_ZoneInfo *self_zinfo = (PyZoneInfo_ZoneInfo *)self;
+    if (load_data(state, self_zinfo, file_obj)) {
         goto error;
     }
 
@@ -262,7 +265,7 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
     }
     Py_DECREF(rv);
 
-    ((PyZoneInfo_ZoneInfo *)self)->key = Py_NewRef(key);
+    self_zinfo->key = Py_NewRef(key);
 
     goto cleanup;
 error:
@@ -346,16 +349,18 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
 }
 
 static int
-zoneinfo_traverse(PyZoneInfo_ZoneInfo *self, visitproc visit, void *arg)
+zoneinfo_traverse(PyObject *op, visitproc visit, void *arg)
 {
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
     Py_VISIT(Py_TYPE(self));
     Py_VISIT(self->key);
     return 0;
 }
 
 static int
-zoneinfo_clear(PyZoneInfo_ZoneInfo *self)
+zoneinfo_clear(PyObject *op)
 {
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
     Py_CLEAR(self->key);
     Py_CLEAR(self->file_repr);
     return 0;
@@ -364,7 +369,7 @@ zoneinfo_clear(PyZoneInfo_ZoneInfo *self)
 static void
 zoneinfo_dealloc(PyObject *obj_self)
 {
-    PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
 
@@ -395,7 +400,7 @@ zoneinfo_dealloc(PyObject *obj_self)
 
     free_tzrule(&(self->tzrule_after));
 
-    zoneinfo_clear(self);
+    (void)zoneinfo_clear(obj_self);
     tp->tp_free(obj_self);
     Py_DECREF(tp);
 }
@@ -420,8 +425,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls,
     PyObject *file_repr = NULL;
     PyZoneInfo_ZoneInfo *self = NULL;
 
-    PyObject *obj_self = (PyObject *)(type->tp_alloc(type, 0));
-    self = (PyZoneInfo_ZoneInfo *)obj_self;
+    self = (PyZoneInfo_ZoneInfo *)type->tp_alloc(type, 0);
     if (self == NULL) {
         return NULL;
     }
@@ -439,7 +443,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls,
     self->source = SOURCE_FILE;
     self->file_repr = file_repr;
     self->key = Py_NewRef(key);
-    return obj_self;
+    return (PyObject *)self;
 
 error:
     Py_XDECREF(file_repr);
@@ -466,7 +470,7 @@ zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyTypeObject *cls,
     zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
     PyObject *out = zoneinfo_new_instance(state, type, key);
     if (out != NULL) {
-        ((PyZoneInfo_ZoneInfo *)out)->source = SOURCE_NOCACHE;
+        PyZoneInfo_ZoneInfo_CAST(out)->source = SOURCE_NOCACHE;
     }
 
     return out;
@@ -558,7 +562,7 @@ zoneinfo_ZoneInfo_utcoffset_impl(PyObject *self, PyTypeObject *cls,
 /*[clinic end generated code: output=b71016c319ba1f91 input=2bb6c5364938f19c]*/
 {
     zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
-    _ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
+    _ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
     if (tti == NULL) {
         return NULL;
     }
@@ -580,7 +584,7 @@ zoneinfo_ZoneInfo_dst_impl(PyObject *self, PyTypeObject *cls, PyObject *dt)
 /*[clinic end generated code: output=cb6168d7723a6ae6 input=2167fb80cf8645c6]*/
 {
     zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
-    _ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
+    _ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
     if (tti == NULL) {
         return NULL;
     }
@@ -603,7 +607,7 @@ zoneinfo_ZoneInfo_tzname_impl(PyObject *self, PyTypeObject *cls,
 /*[clinic end generated code: output=3b6ae6c3053ea75a input=15a59a4f92ed1f1f]*/
 {
     zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
-    _ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
+    _ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
     if (tti == NULL) {
         return NULL;
     }
@@ -627,7 +631,7 @@ zoneinfo_fromutc(PyObject *obj_self, PyObject *dt)
         return NULL;
     }
 
-    PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
 
     int64_t timestamp;
     if (get_local_timestamp(dt, &timestamp)) {
@@ -736,31 +740,24 @@ zoneinfo_fromutc(PyObject *obj_self, PyObject *dt)
 }
 
 static PyObject *
-zoneinfo_repr(PyZoneInfo_ZoneInfo *self)
+zoneinfo_repr(PyObject *op)
 {
-    PyObject *rv = NULL;
-    const char *type_name = Py_TYPE((PyObject *)self)->tp_name;
-    if (!(self->key == Py_None)) {
-        rv = PyUnicode_FromFormat("%s(key=%R)", type_name, self->key);
-    }
-    else {
-        assert(PyUnicode_Check(self->file_repr));
-        rv = PyUnicode_FromFormat("%s.from_file(%U)", type_name,
-                                  self->file_repr);
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
+    if (self->key != Py_None) {
+        return PyUnicode_FromFormat("%T(key=%R)", self, self->key);
     }
-
-    return rv;
+    assert(PyUnicode_Check(self->file_repr));
+    return PyUnicode_FromFormat("%T.from_file(%U)", self, self->file_repr);
 }
 
 static PyObject *
-zoneinfo_str(PyZoneInfo_ZoneInfo *self)
+zoneinfo_str(PyObject *op)
 {
-    if (!(self->key == Py_None)) {
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
+    if (self->key != Py_None) {
         return Py_NewRef(self->key);
     }
-    else {
-        return zoneinfo_repr(self);
-    }
+    return zoneinfo_repr(op);
 }
 
 /* Pickles the ZoneInfo object by key and source.
@@ -776,9 +773,9 @@ zoneinfo_str(PyZoneInfo_ZoneInfo *self)
  * Objects constructed from ZoneInfo.from_file cannot be pickled.
  */
 static PyObject *
-zoneinfo_reduce(PyObject *obj_self, PyObject *unused)
+zoneinfo_reduce(PyObject *obj_self, PyObject *Py_UNUSED(dummy))
 {
-    PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
+    PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
     if (self->source == SOURCE_FILE) {
         // Objects constructed from files cannot be pickled.
         PyObject *pickle_error =