Skip to content

Commit 18bc5b7

Browse files
authored
gh-111178: fix UBSan failures in Modules/_zoneinfo.c (GH-129798)
Fix UBSan failures for `PyZoneInfo_ZoneInfo` Fix semantic naming
1 parent b536e37 commit 18bc5b7

File tree

1 file changed

+31
-34
lines changed

1 file changed

+31
-34
lines changed

Modules/_zoneinfo.c

+31-34
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ typedef struct {
5656
unsigned char source;
5757
} PyZoneInfo_ZoneInfo;
5858

59+
#define PyZoneInfo_ZoneInfo_CAST(op) ((PyZoneInfo_ZoneInfo *)(op))
60+
5961
struct TransitionRuleType {
6062
int64_t (*year_to_timestamp)(TransitionRuleType *, int);
6163
};
@@ -238,7 +240,7 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
238240
}
239241
}
240242

241-
PyObject *self = (PyObject *)(type->tp_alloc(type, 0));
243+
PyObject *self = type->tp_alloc(type, 0);
242244
if (self == NULL) {
243245
goto error;
244246
}
@@ -251,7 +253,8 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
251253
}
252254
}
253255

254-
if (load_data(state, (PyZoneInfo_ZoneInfo *)self, file_obj)) {
256+
PyZoneInfo_ZoneInfo *self_zinfo = (PyZoneInfo_ZoneInfo *)self;
257+
if (load_data(state, self_zinfo, file_obj)) {
255258
goto error;
256259
}
257260

@@ -262,7 +265,7 @@ zoneinfo_new_instance(zoneinfo_state *state, PyTypeObject *type, PyObject *key)
262265
}
263266
Py_DECREF(rv);
264267

265-
((PyZoneInfo_ZoneInfo *)self)->key = Py_NewRef(key);
268+
self_zinfo->key = Py_NewRef(key);
266269

267270
goto cleanup;
268271
error:
@@ -346,16 +349,18 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
346349
}
347350

348351
static int
349-
zoneinfo_traverse(PyZoneInfo_ZoneInfo *self, visitproc visit, void *arg)
352+
zoneinfo_traverse(PyObject *op, visitproc visit, void *arg)
350353
{
354+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
351355
Py_VISIT(Py_TYPE(self));
352356
Py_VISIT(self->key);
353357
return 0;
354358
}
355359

356360
static int
357-
zoneinfo_clear(PyZoneInfo_ZoneInfo *self)
361+
zoneinfo_clear(PyObject *op)
358362
{
363+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
359364
Py_CLEAR(self->key);
360365
Py_CLEAR(self->file_repr);
361366
return 0;
@@ -364,7 +369,7 @@ zoneinfo_clear(PyZoneInfo_ZoneInfo *self)
364369
static void
365370
zoneinfo_dealloc(PyObject *obj_self)
366371
{
367-
PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
372+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
368373
PyTypeObject *tp = Py_TYPE(self);
369374
PyObject_GC_UnTrack(self);
370375

@@ -395,7 +400,7 @@ zoneinfo_dealloc(PyObject *obj_self)
395400

396401
free_tzrule(&(self->tzrule_after));
397402

398-
zoneinfo_clear(self);
403+
(void)zoneinfo_clear(obj_self);
399404
tp->tp_free(obj_self);
400405
Py_DECREF(tp);
401406
}
@@ -420,8 +425,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls,
420425
PyObject *file_repr = NULL;
421426
PyZoneInfo_ZoneInfo *self = NULL;
422427

423-
PyObject *obj_self = (PyObject *)(type->tp_alloc(type, 0));
424-
self = (PyZoneInfo_ZoneInfo *)obj_self;
428+
self = (PyZoneInfo_ZoneInfo *)type->tp_alloc(type, 0);
425429
if (self == NULL) {
426430
return NULL;
427431
}
@@ -439,7 +443,7 @@ zoneinfo_ZoneInfo_from_file_impl(PyTypeObject *type, PyTypeObject *cls,
439443
self->source = SOURCE_FILE;
440444
self->file_repr = file_repr;
441445
self->key = Py_NewRef(key);
442-
return obj_self;
446+
return (PyObject *)self;
443447

444448
error:
445449
Py_XDECREF(file_repr);
@@ -466,7 +470,7 @@ zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyTypeObject *cls,
466470
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
467471
PyObject *out = zoneinfo_new_instance(state, type, key);
468472
if (out != NULL) {
469-
((PyZoneInfo_ZoneInfo *)out)->source = SOURCE_NOCACHE;
473+
PyZoneInfo_ZoneInfo_CAST(out)->source = SOURCE_NOCACHE;
470474
}
471475

472476
return out;
@@ -558,7 +562,7 @@ zoneinfo_ZoneInfo_utcoffset_impl(PyObject *self, PyTypeObject *cls,
558562
/*[clinic end generated code: output=b71016c319ba1f91 input=2bb6c5364938f19c]*/
559563
{
560564
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
561-
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
565+
_ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
562566
if (tti == NULL) {
563567
return NULL;
564568
}
@@ -580,7 +584,7 @@ zoneinfo_ZoneInfo_dst_impl(PyObject *self, PyTypeObject *cls, PyObject *dt)
580584
/*[clinic end generated code: output=cb6168d7723a6ae6 input=2167fb80cf8645c6]*/
581585
{
582586
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
583-
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
587+
_ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
584588
if (tti == NULL) {
585589
return NULL;
586590
}
@@ -603,7 +607,7 @@ zoneinfo_ZoneInfo_tzname_impl(PyObject *self, PyTypeObject *cls,
603607
/*[clinic end generated code: output=3b6ae6c3053ea75a input=15a59a4f92ed1f1f]*/
604608
{
605609
zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
606-
_ttinfo *tti = find_ttinfo(state, (PyZoneInfo_ZoneInfo *)self, dt);
610+
_ttinfo *tti = find_ttinfo(state, PyZoneInfo_ZoneInfo_CAST(self), dt);
607611
if (tti == NULL) {
608612
return NULL;
609613
}
@@ -627,7 +631,7 @@ zoneinfo_fromutc(PyObject *obj_self, PyObject *dt)
627631
return NULL;
628632
}
629633

630-
PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
634+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
631635

632636
int64_t timestamp;
633637
if (get_local_timestamp(dt, &timestamp)) {
@@ -736,31 +740,24 @@ zoneinfo_fromutc(PyObject *obj_self, PyObject *dt)
736740
}
737741

738742
static PyObject *
739-
zoneinfo_repr(PyZoneInfo_ZoneInfo *self)
743+
zoneinfo_repr(PyObject *op)
740744
{
741-
PyObject *rv = NULL;
742-
const char *type_name = Py_TYPE((PyObject *)self)->tp_name;
743-
if (!(self->key == Py_None)) {
744-
rv = PyUnicode_FromFormat("%s(key=%R)", type_name, self->key);
745-
}
746-
else {
747-
assert(PyUnicode_Check(self->file_repr));
748-
rv = PyUnicode_FromFormat("%s.from_file(%U)", type_name,
749-
self->file_repr);
745+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
746+
if (self->key != Py_None) {
747+
return PyUnicode_FromFormat("%T(key=%R)", self, self->key);
750748
}
751-
752-
return rv;
749+
assert(PyUnicode_Check(self->file_repr));
750+
return PyUnicode_FromFormat("%T.from_file(%U)", self, self->file_repr);
753751
}
754752

755753
static PyObject *
756-
zoneinfo_str(PyZoneInfo_ZoneInfo *self)
754+
zoneinfo_str(PyObject *op)
757755
{
758-
if (!(self->key == Py_None)) {
756+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(op);
757+
if (self->key != Py_None) {
759758
return Py_NewRef(self->key);
760759
}
761-
else {
762-
return zoneinfo_repr(self);
763-
}
760+
return zoneinfo_repr(op);
764761
}
765762

766763
/* Pickles the ZoneInfo object by key and source.
@@ -776,9 +773,9 @@ zoneinfo_str(PyZoneInfo_ZoneInfo *self)
776773
* Objects constructed from ZoneInfo.from_file cannot be pickled.
777774
*/
778775
static PyObject *
779-
zoneinfo_reduce(PyObject *obj_self, PyObject *unused)
776+
zoneinfo_reduce(PyObject *obj_self, PyObject *Py_UNUSED(dummy))
780777
{
781-
PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
778+
PyZoneInfo_ZoneInfo *self = PyZoneInfo_ZoneInfo_CAST(obj_self);
782779
if (self->source == SOURCE_FILE) {
783780
// Objects constructed from files cannot be pickled.
784781
PyObject *pickle_error =

0 commit comments

Comments
 (0)