Skip to content

Commit 76d2c68

Browse files
committed
fix UBSan failures for PyDateTime_TimeZone
1 parent 9fee212 commit 76d2c68

File tree

1 file changed

+38
-29
lines changed

1 file changed

+38
-29
lines changed

Modules/_datetimemodule.c

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ typedef struct {
9696
#define PyTZInfo_Check(op) PyObject_TypeCheck(op, TZINFO_TYPE(NO_STATE))
9797
#define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, TZINFO_TYPE(NO_STATE))
9898

99-
#define _PyTimezone_CAST(op) ((PyDateTime_TimeZone *)(op))
99+
#define _PyTimeZone_CAST(op) ((PyDateTime_TimeZone *)(op))
100100
#define PyTimezone_Check(op) PyObject_TypeCheck(op, TIMEZONE_TYPE(NO_STATE))
101101

102102
#define _PyIsoCalendarDate_CAST(op) ((PyDateTime_IsoCalendarDate *)(op))
@@ -4255,28 +4255,31 @@ timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw)
42554255
}
42564256

42574257
static void
4258-
timezone_dealloc(PyDateTime_TimeZone *self)
4258+
timezone_dealloc(PyObject *op)
42594259
{
4260+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
42604261
Py_CLEAR(self->offset);
42614262
Py_CLEAR(self->name);
4262-
Py_TYPE(self)->tp_free((PyObject *)self);
4263+
Py_TYPE(self)->tp_free(self);
42634264
}
42644265

42654266
static PyObject *
4266-
timezone_richcompare(PyDateTime_TimeZone *self,
4267-
PyDateTime_TimeZone *other, int op)
4267+
timezone_richcompare(PyObject *self, PyObject *other, int op)
42684268
{
42694269
if (op != Py_EQ && op != Py_NE)
42704270
Py_RETURN_NOTIMPLEMENTED;
42714271
if (!PyTimezone_Check(other)) {
42724272
Py_RETURN_NOTIMPLEMENTED;
42734273
}
4274-
return delta_richcompare(self->offset, other->offset, op);
4274+
PyDateTime_TimeZone *lhs = _PyTimeZone_CAST(self);
4275+
PyDateTime_TimeZone *rhs = _PyTimeZone_CAST(other);
4276+
return delta_richcompare(lhs->offset, rhs->offset, op);
42754277
}
42764278

42774279
static Py_hash_t
4278-
timezone_hash(PyDateTime_TimeZone *self)
4280+
timezone_hash(PyObject *op)
42794281
{
4282+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
42804283
return delta_hash(self->offset);
42814284
}
42824285

@@ -4295,13 +4298,14 @@ _timezone_check_argument(PyObject *dt, const char *meth)
42954298
}
42964299

42974300
static PyObject *
4298-
timezone_repr(PyDateTime_TimeZone *self)
4301+
timezone_repr(PyObject *op)
42994302
{
43004303
/* Note that although timezone is not subclassable, it is convenient
43014304
to use Py_TYPE(self)->tp_name here. */
4305+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
43024306
const char *type_name = Py_TYPE(self)->tp_name;
43034307

4304-
if ((PyObject *)self == CONST_UTC(NO_STATE)) {
4308+
if (op == CONST_UTC(NO_STATE)) {
43054309
return PyUnicode_FromFormat("%s.utc", type_name);
43064310
}
43074311

@@ -4312,10 +4316,10 @@ timezone_repr(PyDateTime_TimeZone *self)
43124316
self->name);
43134317
}
43144318

4315-
43164319
static PyObject *
4317-
timezone_str(PyDateTime_TimeZone *self)
4320+
timezone_str(PyObject *op)
43184321
{
4322+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
43194323
int hours, minutes, seconds, microseconds;
43204324
PyObject *offset;
43214325
char sign;
@@ -4360,25 +4364,26 @@ timezone_str(PyDateTime_TimeZone *self)
43604364
}
43614365

43624366
static PyObject *
4363-
timezone_tzname(PyDateTime_TimeZone *self, PyObject *dt)
4367+
timezone_tzname(PyObject *op, PyObject *dt)
43644368
{
43654369
if (_timezone_check_argument(dt, "tzname") == -1)
43664370
return NULL;
43674371

4368-
return timezone_str(self);
4372+
return timezone_str(op);
43694373
}
43704374

43714375
static PyObject *
4372-
timezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt)
4376+
timezone_utcoffset(PyObject *op, PyObject *dt)
43734377
{
43744378
if (_timezone_check_argument(dt, "utcoffset") == -1)
43754379
return NULL;
43764380

4381+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
43774382
return Py_NewRef(self->offset);
43784383
}
43794384

43804385
static PyObject *
4381-
timezone_dst(PyObject *self, PyObject *dt)
4386+
timezone_dst(PyObject *op, PyObject *dt)
43824387
{
43834388
if (_timezone_check_argument(dt, "dst") == -1)
43844389
return NULL;
@@ -4387,45 +4392,49 @@ timezone_dst(PyObject *self, PyObject *dt)
43874392
}
43884393

43894394
static PyObject *
4390-
timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt)
4395+
timezone_fromutc(PyObject *op, PyObject *arg)
43914396
{
4392-
if (!PyDateTime_Check(dt)) {
4397+
if (!PyDateTime_Check(arg)) {
43934398
PyErr_SetString(PyExc_TypeError,
43944399
"fromutc: argument must be a datetime");
43954400
return NULL;
43964401
}
4397-
if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
4402+
4403+
PyDateTime_DateTime *dt = (PyDateTime_DateTime *)arg; // fast safe cast
4404+
if (!HASTZINFO(dt) || dt->tzinfo != op) {
43984405
PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
43994406
"is not self");
44004407
return NULL;
44014408
}
44024409

4410+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
44034411
return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1);
44044412
}
44054413

44064414
static PyObject *
4407-
timezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored))
4415+
timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(ignored))
44084416
{
4417+
PyDateTime_TimeZone *self = _PyTimeZone_CAST(op);
44094418
if (self->name == NULL)
44104419
return PyTuple_Pack(1, self->offset);
44114420
return PyTuple_Pack(2, self->offset, self->name);
44124421
}
44134422

44144423
static PyMethodDef timezone_methods[] = {
4415-
{"tzname", (PyCFunction)timezone_tzname, METH_O,
4424+
{"tzname", timezone_tzname, METH_O,
44164425
PyDoc_STR("If name is specified when timezone is created, returns the name."
44174426
" Otherwise returns offset as 'UTC(+|-)HH:MM'.")},
44184427

4419-
{"utcoffset", (PyCFunction)timezone_utcoffset, METH_O,
4428+
{"utcoffset", timezone_utcoffset, METH_O,
44204429
PyDoc_STR("Return fixed offset.")},
44214430

4422-
{"dst", (PyCFunction)timezone_dst, METH_O,
4431+
{"dst", timezone_dst, METH_O,
44234432
PyDoc_STR("Return None.")},
44244433

4425-
{"fromutc", (PyCFunction)timezone_fromutc, METH_O,
4434+
{"fromutc", timezone_fromutc, METH_O,
44264435
PyDoc_STR("datetime in UTC -> datetime in local time.")},
44274436

4428-
{"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS,
4437+
{"__getinitargs__", timezone_getinitargs, METH_NOARGS,
44294438
PyDoc_STR("pickle support")},
44304439

44314440
{NULL, NULL}
@@ -4439,26 +4448,26 @@ static PyTypeObject PyDateTime_TimeZoneType = {
44394448
"datetime.timezone", /* tp_name */
44404449
sizeof(PyDateTime_TimeZone), /* tp_basicsize */
44414450
0, /* tp_itemsize */
4442-
(destructor)timezone_dealloc, /* tp_dealloc */
4451+
timezone_dealloc, /* tp_dealloc */
44434452
0, /* tp_vectorcall_offset */
44444453
0, /* tp_getattr */
44454454
0, /* tp_setattr */
44464455
0, /* tp_as_async */
4447-
(reprfunc)timezone_repr, /* tp_repr */
4456+
timezone_repr, /* tp_repr */
44484457
0, /* tp_as_number */
44494458
0, /* tp_as_sequence */
44504459
0, /* tp_as_mapping */
4451-
(hashfunc)timezone_hash, /* tp_hash */
4460+
timezone_hash, /* tp_hash */
44524461
0, /* tp_call */
4453-
(reprfunc)timezone_str, /* tp_str */
4462+
timezone_str, /* tp_str */
44544463
0, /* tp_getattro */
44554464
0, /* tp_setattro */
44564465
0, /* tp_as_buffer */
44574466
Py_TPFLAGS_DEFAULT, /* tp_flags */
44584467
timezone_doc, /* tp_doc */
44594468
0, /* tp_traverse */
44604469
0, /* tp_clear */
4461-
(richcmpfunc)timezone_richcompare,/* tp_richcompare */
4470+
timezone_richcompare, /* tp_richcompare */
44624471
0, /* tp_weaklistoffset */
44634472
0, /* tp_iter */
44644473
0, /* tp_iternext */

0 commit comments

Comments
 (0)