From d4be207477317426a1e3ae04a10b1efc2499fe3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 11:56:51 +0100 Subject: [PATCH 01/12] add cast macros for date and time objects --- Modules/_datetimemodule.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index ff2e6d6a098ad9..3811a928cd6bb3 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -58,7 +58,13 @@ typedef struct { * the per-module objects stored in module state. The macros for the * static objects don't need to be passed a state, but the consistency * of doing so is more clear. We use a dedicated noop macro, NO_STATE, - * to make the special case obvious. */ + * to make the special case obvious. + * + * The casting macros perform a simple fast pointer cast without + * checking the runtime type. In the future, we may decide whether + * to include that check and whether to provide a fast pointer cast + * macro for pointers known to be of correct time. + */ #define NO_STATE NULL @@ -70,23 +76,31 @@ typedef struct { #define TIMEZONE_TYPE(st) &PyDateTime_TimeZoneType #define ISOCALENDAR_DATE_TYPE(st) st->isocalendar_date_type +#define _PyDate_CAST(op) ((PyDateTime_Date *)(op)) #define PyDate_Check(op) PyObject_TypeCheck(op, DATE_TYPE(NO_STATE)) #define PyDate_CheckExact(op) Py_IS_TYPE(op, DATE_TYPE(NO_STATE)) +#define _PyDateTime_CAST(op) ((PyDateTime_DateTime *)(op)) #define PyDateTime_Check(op) PyObject_TypeCheck(op, DATETIME_TYPE(NO_STATE)) #define PyDateTime_CheckExact(op) Py_IS_TYPE(op, DATETIME_TYPE(NO_STATE)) +#define _PyTime_CAST(op) ((PyDateTime_Time *)(op)) #define PyTime_Check(op) PyObject_TypeCheck(op, TIME_TYPE(NO_STATE)) #define PyTime_CheckExact(op) Py_IS_TYPE(op, TIME_TYPE(NO_STATE)) +#define _PyDelta_CAST(op) ((PyDateTime_Delta *)(op)) #define PyDelta_Check(op) PyObject_TypeCheck(op, DELTA_TYPE(NO_STATE)) #define PyDelta_CheckExact(op) Py_IS_TYPE(op, DELTA_TYPE(NO_STATE)) +#define _PyTZInfo_CAST(op) ((PyDateTime_TZInfo *)(op)) #define PyTZInfo_Check(op) PyObject_TypeCheck(op, TZINFO_TYPE(NO_STATE)) #define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, TZINFO_TYPE(NO_STATE)) +#define _PyTimezone_CAST(op) ((PyDateTime_TimeZone *)(op)) #define PyTimezone_Check(op) PyObject_TypeCheck(op, TIMEZONE_TYPE(NO_STATE)) +#define _PyIsoCalendarDate_CAST(op) ((PyDateTime_IsoCalendarDate *)(op)) + #define CONST_US_PER_MS(st) st->us_per_ms #define CONST_US_PER_SECOND(st) st->us_per_second #define CONST_US_PER_MINUTE(st) st->us_per_minute From 6d1f2633f76738d5cd0a229733589607bfd8764c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:19:35 +0100 Subject: [PATCH 02/12] fix UBSan failures for `PyDateTime_Delta` --- Modules/_datetimemodule.c | 60 ++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 3811a928cd6bb3..b15f7cf56e3cc0 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -309,9 +309,9 @@ clear_current_module(PyInterpreterState *interp, PyObject *expected) #define TIME_SET_FOLD(o, v) (PyDateTime_TIME_GET_FOLD(o) = (v)) /* Delta accessors for timedelta. */ -#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days) -#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds) -#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds) +#define GET_TD_DAYS(o) (_PyDelta_CAST(o)->days) +#define GET_TD_SECONDS(o) (_PyDelta_CAST(o)->seconds) +#define GET_TD_MICROSECONDS(o) (_PyDelta_CAST(o)->microseconds) #define SET_TD_DAYS(o, v) ((o)->days = (v)) #define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) @@ -1430,7 +1430,7 @@ create_timezone(PyObject *offset, PyObject *name) return (PyObject *)self; } -static int delta_bool(PyDateTime_Delta *self); +static int delta_bool(PyObject *op); static PyDateTime_TimeZone utc_timezone; static PyObject * @@ -1440,7 +1440,7 @@ new_timezone(PyObject *offset, PyObject *name) assert(PyDelta_Check(offset)); assert(name == NULL || PyUnicode_Check(name)); - if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) { + if (name == NULL && delta_bool(offset) == 0) { return Py_NewRef(CONST_UTC(NO_STATE)); } if ((GET_TD_DAYS(offset) == -1 && @@ -1694,7 +1694,7 @@ format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds) GET_YEAR(date)); } -static PyObject *delta_negative(PyDateTime_Delta *self); +static PyObject *delta_negative(PyObject *op); /* Add formatted UTC offset string to buf. buf has no more than * buflen bytes remaining. The UTC offset is gotten by calling @@ -1727,7 +1727,7 @@ format_utcoffset(char *buf, size_t buflen, const char *sep, /* Offset is normalized, so it is negative if days < 0 */ if (GET_TD_DAYS(offset) < 0) { sign = '-'; - Py_SETREF(offset, delta_negative((PyDateTime_Delta *)offset)); + Py_SETREF(offset, delta_negative(offset)); if (offset == NULL) return -1; } @@ -2429,7 +2429,7 @@ delta_add(PyObject *left, PyObject *right) } static PyObject * -delta_negative(PyDateTime_Delta *self) +delta_negative(PyObject *self) { return new_delta(-GET_TD_DAYS(self), -GET_TD_SECONDS(self), @@ -2438,7 +2438,7 @@ delta_negative(PyDateTime_Delta *self) } static PyObject * -delta_positive(PyDateTime_Delta *self) +delta_positive(PyObject *self) { /* Could optimize this (by returning self) if this isn't a * subclass -- but who uses unary + ? Approximately nobody. @@ -2450,7 +2450,7 @@ delta_positive(PyDateTime_Delta *self) } static PyObject * -delta_abs(PyDateTime_Delta *self) +delta_abs(PyObject *self) { PyObject *result; @@ -2515,8 +2515,9 @@ delta_richcompare(PyObject *self, PyObject *other, int op) static PyObject *delta_getstate(PyDateTime_Delta *self); static Py_hash_t -delta_hash(PyDateTime_Delta *self) +delta_hash(PyObject *op) { + PyDateTime_Delta *self = _PyDelta_CAST(op); if (self->hashcode == -1) { PyObject *temp = delta_getstate(self); if (temp != NULL) { @@ -2880,7 +2881,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw) } static int -delta_bool(PyDateTime_Delta *self) +delta_bool(PyObject *self) { return (GET_TD_DAYS(self) != 0 || GET_TD_SECONDS(self) != 0 @@ -2888,7 +2889,7 @@ delta_bool(PyDateTime_Delta *self) } static PyObject * -delta_repr(PyDateTime_Delta *self) +delta_repr(PyObject *self) { PyObject *args = Py_GetConstant(Py_CONSTANT_EMPTY_STR); @@ -2937,7 +2938,7 @@ delta_repr(PyDateTime_Delta *self) } static PyObject * -delta_str(PyDateTime_Delta *self) +delta_str(PyObject *self) { int us = GET_TD_MICROSECONDS(self); int seconds = GET_TD_SECONDS(self); @@ -2977,12 +2978,12 @@ delta_getstate(PyDateTime_Delta *self) } static PyObject * -delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored)) +delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(closure)) { PyObject *total_seconds; PyObject *total_microseconds; - total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self); + total_microseconds = delta_to_microseconds(_PyDelta_CAST(op)); if (total_microseconds == NULL) return NULL; @@ -2997,8 +2998,9 @@ delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -delta_reduce(PyDateTime_Delta* self, PyObject *Py_UNUSED(ignored)) +delta_reduce(PyObject *op, PyObject *Py_UNUSED(closure)) { + PyDateTime_Delta *self = _PyDelta_CAST(op); return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self)); } @@ -3021,7 +3023,7 @@ static PyMethodDef delta_methods[] = { {"total_seconds", delta_total_seconds, METH_NOARGS, PyDoc_STR("Total seconds in the duration.")}, - {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS, + {"__reduce__", delta_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, {NULL, NULL}, @@ -3041,10 +3043,10 @@ static PyNumberMethods delta_as_number = { delta_remainder, /* nb_remainder */ delta_divmod, /* nb_divmod */ 0, /* nb_power */ - (unaryfunc)delta_negative, /* nb_negative */ - (unaryfunc)delta_positive, /* nb_positive */ - (unaryfunc)delta_abs, /* nb_absolute */ - (inquiry)delta_bool, /* nb_bool */ + delta_negative, /* nb_negative */ + delta_positive, /* nb_positive */ + delta_abs, /* nb_absolute */ + delta_bool, /* nb_bool */ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ @@ -3080,13 +3082,13 @@ static PyTypeObject PyDateTime_DeltaType = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)delta_repr, /* tp_repr */ + delta_repr, /* tp_repr */ &delta_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)delta_hash, /* tp_hash */ + delta_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)delta_str, /* tp_str */ + delta_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -4113,7 +4115,7 @@ tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) goto Fail; if (dst == Py_None) goto Inconsistent; - if (delta_bool((PyDateTime_Delta *)dst) != 0) { + if (delta_bool(dst) != 0) { Py_SETREF(result, add_datetime_timedelta((PyDateTime_DateTime *)result, (PyDateTime_Delta *)dst, 1)); if (result == NULL) @@ -4274,7 +4276,7 @@ timezone_richcompare(PyDateTime_TimeZone *self, static Py_hash_t timezone_hash(PyDateTime_TimeZone *self) { - return delta_hash((PyDateTime_Delta *)self->offset); + return delta_hash(self->offset); } /* Check argument type passed to tzname, utcoffset, or dst methods. @@ -4330,7 +4332,7 @@ timezone_str(PyDateTime_TimeZone *self) /* Offset is normalized, so it is negative if days < 0 */ if (GET_TD_DAYS(self->offset) < 0) { sign = '-'; - offset = delta_negative((PyDateTime_Delta *)self->offset); + offset = delta_negative(self->offset); if (offset == NULL) return NULL; } @@ -6726,7 +6728,7 @@ datetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) return NULL; if (dst != Py_None) - dstflag = delta_bool((PyDateTime_Delta *)dst); + dstflag = delta_bool(dst); Py_DECREF(dst); } return build_struct_time(GET_YEAR(self), From 1aeeff8da9c7d17a679bafc14145485e738c3b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:30:37 +0100 Subject: [PATCH 03/12] fix UBSan failures for `PyDateTime_Date` --- Modules/_datetimemodule.c | 105 +++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index b15f7cf56e3cc0..4810acf6bb60a4 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1676,7 +1676,7 @@ tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds) */ static PyObject * -format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds) +format_ctime(PyObject *date, int hours, int minutes, int seconds) { static const char * const DayNames[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" @@ -3140,27 +3140,30 @@ look_up_delta(int days, int seconds, int microseconds, PyTypeObject *type) /* Accessor properties. */ static PyObject * -date_year(PyDateTime_Date *self, void *unused) +date_year(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Date *self = _PyDate_CAST(op); return PyLong_FromLong(GET_YEAR(self)); } static PyObject * -date_month(PyDateTime_Date *self, void *unused) +date_month(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Date *self = _PyDate_CAST(op); return PyLong_FromLong(GET_MONTH(self)); } static PyObject * -date_day(PyDateTime_Date *self, void *unused) +date_day(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Date *self = _PyDate_CAST(op); return PyLong_FromLong(GET_DAY(self)); } static PyGetSetDef date_getset[] = { - {"year", (getter)date_year}, - {"month", (getter)date_month}, - {"day", (getter)date_day}, + {"year", date_year}, + {"month", date_month}, + {"day", date_day}, {NULL} }; @@ -3519,36 +3522,38 @@ date_subtract(PyObject *left, PyObject *right) /* Various ways to turn a date into a string. */ static PyObject * -date_repr(PyDateTime_Date *self) +date_repr(PyObject *op) { + PyDateTime_Date *self = _PyDate_CAST(op); return PyUnicode_FromFormat("%s(%d, %d, %d)", Py_TYPE(self)->tp_name, GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); } static PyObject * -date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_isoformat(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_Date *self = _PyDate_CAST(op); return PyUnicode_FromFormat("%04d-%02d-%02d", GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); } /* str() calls the appropriate isoformat() method. */ static PyObject * -date_str(PyDateTime_Date *self) +date_str(PyObject *self) { - return PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(isoformat)); + return PyObject_CallMethodNoArgs(self, &_Py_ID(isoformat)); } static PyObject * -date_ctime(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_ctime(PyObject *self, PyObject *Py_UNUSED(ignored)) { return format_ctime(self, 0, 0, 0); } static PyObject * -date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw) +date_strftime(PyObject *self, PyObject *args, PyObject *kw) { /* This method can be inherited, and needs to call the * timetuple() method appropriate to self's class. @@ -3558,21 +3563,20 @@ date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw) PyObject *format; static char *keywords[] = {"format", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, - &format)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, + &format)) return NULL; - tuple = PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(timetuple)); + tuple = PyObject_CallMethodNoArgs(self, &_Py_ID(timetuple)); if (tuple == NULL) return NULL; - result = wrap_strftime((PyObject *)self, format, tuple, - (PyObject *)self); + result = wrap_strftime(self, format, tuple, self); Py_DECREF(tuple); return result; } static PyObject * -date_format(PyDateTime_Date *self, PyObject *args) +date_format(PyObject *self, PyObject *args) { PyObject *format; @@ -3581,16 +3585,15 @@ date_format(PyDateTime_Date *self, PyObject *args) /* if the format is zero length, return str(self) */ if (PyUnicode_GetLength(format) == 0) - return PyObject_Str((PyObject *)self); + return PyObject_Str(self); - return PyObject_CallMethodOneArg((PyObject *)self, &_Py_ID(strftime), - format); + return PyObject_CallMethodOneArg(self, &_Py_ID(strftime), format); } /* ISO methods. */ static PyObject * -date_isoweekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_isoweekday(PyObject *self, PyObject *Py_UNUSED(ignored)) { int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); @@ -3748,7 +3751,7 @@ iso_calendar_date_new_impl(PyTypeObject *type, int year, int week, } static PyObject * -date_isocalendar(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_isocalendar(PyObject *self, PyObject *Py_UNUSED(ignored)) { int year = GET_YEAR(self); int week1_monday = iso_week1_monday(year); @@ -3803,7 +3806,7 @@ date_richcompare(PyObject *self, PyObject *other, int op) } static PyObject * -date_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_timetuple(PyObject *self, PyObject *Py_UNUSED(ignored)) { return build_struct_time(GET_YEAR(self), GET_MONTH(self), @@ -3839,8 +3842,9 @@ generic_hash(unsigned char *data, int len) static PyObject *date_getstate(PyDateTime_Date *self); static Py_hash_t -date_hash(PyDateTime_Date *self) +date_hash(PyObject *op) { + PyDateTime_Date *self = _PyDate_CAST(op); if (self->hashcode == -1) { self->hashcode = generic_hash( (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE); @@ -3850,17 +3854,16 @@ date_hash(PyDateTime_Date *self) } static PyObject * -date_toordinal(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_toordinal(PyObject *self, PyObject *Py_UNUSED(ignored)) { return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self), - GET_DAY(self))); + GET_DAY(self))); } static PyObject * -date_weekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) +date_weekday(PyObject *self, PyObject *Py_UNUSED(ignored)) { int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); - return PyLong_FromLong(dow); } @@ -3877,8 +3880,9 @@ date_getstate(PyDateTime_Date *self) } static PyObject * -date_reduce(PyDateTime_Date *self, PyObject *arg) +date_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_Date *self = _PyDate_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self)); } @@ -3887,13 +3891,11 @@ static PyMethodDef date_methods[] = { /* Class methods: */ DATETIME_DATE_FROMTIMESTAMP_METHODDEF - {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS | - METH_CLASS, + {"fromordinal", date_fromordinal, METH_VARARGS | METH_CLASS, PyDoc_STR("int -> date corresponding to a proleptic Gregorian " "ordinal.")}, - {"fromisoformat", (PyCFunction)date_fromisoformat, METH_O | - METH_CLASS, + {"fromisoformat", date_fromisoformat, METH_O | METH_CLASS, PyDoc_STR("str -> Construct a date from a string in ISO 8601 format.")}, {"fromisocalendar", _PyCFunction_CAST(date_fromisocalendar), @@ -3902,45 +3904,44 @@ static PyMethodDef date_methods[] = { "number and weekday.\n\n" "This is the inverse of the date.isocalendar() function")}, - {"strptime", (PyCFunction)date_strptime, - METH_VARARGS | METH_CLASS, + {"strptime", date_strptime, METH_VARARGS | METH_CLASS, PyDoc_STR("string, format -> new date parsed from a string " "(like time.strptime()).")}, - {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS, + {"today", date_today, METH_NOARGS | METH_CLASS, PyDoc_STR("Current date or datetime: same as " "self.__class__.fromtimestamp(time.time()).")}, /* Instance methods: */ - {"ctime", (PyCFunction)date_ctime, METH_NOARGS, + {"ctime", date_ctime, METH_NOARGS, PyDoc_STR("Return ctime() style string.")}, - {"strftime", _PyCFunction_CAST(date_strftime), METH_VARARGS | METH_KEYWORDS, + {"strftime", _PyCFunction_CAST(date_strftime), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("format -> strftime() style string.")}, - {"__format__", (PyCFunction)date_format, METH_VARARGS, + {"__format__", date_format, METH_VARARGS, PyDoc_STR("Formats self with strftime.")}, - {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS, + {"timetuple", date_timetuple, METH_NOARGS, PyDoc_STR("Return time tuple, compatible with time.localtime().")}, - {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS, + {"isocalendar", date_isocalendar, METH_NOARGS, PyDoc_STR("Return a named tuple containing ISO year, week number, and " "weekday.")}, - {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS, + {"isoformat", date_isoformat, METH_NOARGS, PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")}, - {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS, + {"isoweekday", date_isoweekday, METH_NOARGS, PyDoc_STR("Return the day of the week represented by the date.\n" "Monday == 1 ... Sunday == 7")}, - {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS, + {"toordinal", date_toordinal, METH_NOARGS, PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year " "1 is day 1.")}, - {"weekday", (PyCFunction)date_weekday, METH_NOARGS, + {"weekday", date_weekday, METH_NOARGS, PyDoc_STR("Return the day of the week represented by the date.\n" "Monday == 0 ... Sunday == 6")}, @@ -3949,7 +3950,7 @@ static PyMethodDef date_methods[] = { {"__replace__", _PyCFunction_CAST(datetime_date_replace), METH_FASTCALL | METH_KEYWORDS, PyDoc_STR("__replace__($self, /, **changes)\n--\n\nThe same as replace().")}, - {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS, + {"__reduce__", date_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, {NULL, NULL} @@ -3981,13 +3982,13 @@ static PyTypeObject PyDateTime_DateType = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)date_repr, /* tp_repr */ + date_repr, /* tp_repr */ &date_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)date_hash, /* tp_hash */ + date_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)date_str, /* tp_str */ + date_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -6240,7 +6241,7 @@ datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) static PyObject * datetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) { - return format_ctime((PyDateTime_Date *)self, + return format_ctime((PyObject *)self, DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self)); From 9fee212880c9a3cd264bd1fbca85fc4593f77077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:34:14 +0100 Subject: [PATCH 04/12] fix UBSan failures for `PyDateTime_TZInfo` --- Modules/_datetimemodule.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 4810acf6bb60a4..bf589b86addf58 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4043,19 +4043,19 @@ tzinfo_nogo(const char* methodname) /* Methods. A subclass must implement these. */ static PyObject * -tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt) +tzinfo_tzname(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(dt)) { return tzinfo_nogo("tzname"); } static PyObject * -tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt) +tzinfo_utcoffset(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(dt)) { return tzinfo_nogo("utcoffset"); } static PyObject * -tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt) +tzinfo_dst(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(dt)) { return tzinfo_nogo("dst"); } @@ -4068,7 +4068,7 @@ static PyObject *datetime_utcoffset(PyObject *self, PyObject *); static PyObject *datetime_dst(PyObject *self, PyObject *); static PyObject * -tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) +tzinfo_fromutc(PyObject *self, PyObject *dt) { PyObject *result = NULL; PyObject *off = NULL, *dst = NULL; @@ -4079,7 +4079,7 @@ tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) "fromutc: argument must be a datetime"); return NULL; } - if (GET_DT_TZINFO(dt) != (PyObject *)self) { + if (GET_DT_TZINFO(dt) != self) { PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " "is not self"); return NULL; @@ -4176,20 +4176,20 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyMethodDef tzinfo_methods[] = { - {"tzname", (PyCFunction)tzinfo_tzname, METH_O, + {"tzname", tzinfo_tzname, METH_O, PyDoc_STR("datetime -> string name of time zone.")}, - {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, + {"utcoffset", tzinfo_utcoffset, METH_O, PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " "values indicating West of UTC")}, - {"dst", (PyCFunction)tzinfo_dst, METH_O, + {"dst", tzinfo_dst, METH_O, PyDoc_STR("datetime -> DST offset as timedelta positive east of UTC.")}, - {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O, + {"fromutc", tzinfo_fromutc, METH_O, PyDoc_STR("datetime in UTC -> datetime in local time.")}, - {"__reduce__", tzinfo_reduce, METH_NOARGS, + {"__reduce__", tzinfo_reduce, METH_NOARGS, PyDoc_STR("-> (cls, state)")}, {NULL, NULL} From 76d2c68fa82dd0691d7373e7ff6b769a7704db88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:43:31 +0100 Subject: [PATCH 05/12] fix UBSan failures for `PyDateTime_TimeZone` --- Modules/_datetimemodule.c | 67 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index bf589b86addf58..797b7b28aaf4b1 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -96,7 +96,7 @@ typedef struct { #define PyTZInfo_Check(op) PyObject_TypeCheck(op, TZINFO_TYPE(NO_STATE)) #define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, TZINFO_TYPE(NO_STATE)) -#define _PyTimezone_CAST(op) ((PyDateTime_TimeZone *)(op)) +#define _PyTimeZone_CAST(op) ((PyDateTime_TimeZone *)(op)) #define PyTimezone_Check(op) PyObject_TypeCheck(op, TIMEZONE_TYPE(NO_STATE)) #define _PyIsoCalendarDate_CAST(op) ((PyDateTime_IsoCalendarDate *)(op)) @@ -4255,28 +4255,31 @@ timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw) } static void -timezone_dealloc(PyDateTime_TimeZone *self) +timezone_dealloc(PyObject *op) { + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); Py_CLEAR(self->offset); Py_CLEAR(self->name); - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free(self); } static PyObject * -timezone_richcompare(PyDateTime_TimeZone *self, - PyDateTime_TimeZone *other, int op) +timezone_richcompare(PyObject *self, PyObject *other, int op) { if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED; if (!PyTimezone_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } - return delta_richcompare(self->offset, other->offset, op); + PyDateTime_TimeZone *lhs = _PyTimeZone_CAST(self); + PyDateTime_TimeZone *rhs = _PyTimeZone_CAST(other); + return delta_richcompare(lhs->offset, rhs->offset, op); } static Py_hash_t -timezone_hash(PyDateTime_TimeZone *self) +timezone_hash(PyObject *op) { + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); return delta_hash(self->offset); } @@ -4295,13 +4298,14 @@ _timezone_check_argument(PyObject *dt, const char *meth) } static PyObject * -timezone_repr(PyDateTime_TimeZone *self) +timezone_repr(PyObject *op) { /* Note that although timezone is not subclassable, it is convenient to use Py_TYPE(self)->tp_name here. */ + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; - if ((PyObject *)self == CONST_UTC(NO_STATE)) { + if (op == CONST_UTC(NO_STATE)) { return PyUnicode_FromFormat("%s.utc", type_name); } @@ -4312,10 +4316,10 @@ timezone_repr(PyDateTime_TimeZone *self) self->name); } - static PyObject * -timezone_str(PyDateTime_TimeZone *self) +timezone_str(PyObject *op) { + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); int hours, minutes, seconds, microseconds; PyObject *offset; char sign; @@ -4360,25 +4364,26 @@ timezone_str(PyDateTime_TimeZone *self) } static PyObject * -timezone_tzname(PyDateTime_TimeZone *self, PyObject *dt) +timezone_tzname(PyObject *op, PyObject *dt) { if (_timezone_check_argument(dt, "tzname") == -1) return NULL; - return timezone_str(self); + return timezone_str(op); } static PyObject * -timezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt) +timezone_utcoffset(PyObject *op, PyObject *dt) { if (_timezone_check_argument(dt, "utcoffset") == -1) return NULL; + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); return Py_NewRef(self->offset); } static PyObject * -timezone_dst(PyObject *self, PyObject *dt) +timezone_dst(PyObject *op, PyObject *dt) { if (_timezone_check_argument(dt, "dst") == -1) return NULL; @@ -4387,45 +4392,49 @@ timezone_dst(PyObject *self, PyObject *dt) } static PyObject * -timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) +timezone_fromutc(PyObject *op, PyObject *arg) { - if (!PyDateTime_Check(dt)) { + if (!PyDateTime_Check(arg)) { PyErr_SetString(PyExc_TypeError, "fromutc: argument must be a datetime"); return NULL; } - if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { + + PyDateTime_DateTime *dt = (PyDateTime_DateTime *)arg; // fast safe cast + if (!HASTZINFO(dt) || dt->tzinfo != op) { PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " "is not self"); return NULL; } + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); } static PyObject * -timezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored)) +timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); if (self->name == NULL) return PyTuple_Pack(1, self->offset); return PyTuple_Pack(2, self->offset, self->name); } static PyMethodDef timezone_methods[] = { - {"tzname", (PyCFunction)timezone_tzname, METH_O, + {"tzname", timezone_tzname, METH_O, PyDoc_STR("If name is specified when timezone is created, returns the name." " Otherwise returns offset as 'UTC(+|-)HH:MM'.")}, - {"utcoffset", (PyCFunction)timezone_utcoffset, METH_O, + {"utcoffset", timezone_utcoffset, METH_O, PyDoc_STR("Return fixed offset.")}, - {"dst", (PyCFunction)timezone_dst, METH_O, + {"dst", timezone_dst, METH_O, PyDoc_STR("Return None.")}, - {"fromutc", (PyCFunction)timezone_fromutc, METH_O, + {"fromutc", timezone_fromutc, METH_O, PyDoc_STR("datetime in UTC -> datetime in local time.")}, - {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS, + {"__getinitargs__", timezone_getinitargs, METH_NOARGS, PyDoc_STR("pickle support")}, {NULL, NULL} @@ -4439,18 +4448,18 @@ static PyTypeObject PyDateTime_TimeZoneType = { "datetime.timezone", /* tp_name */ sizeof(PyDateTime_TimeZone), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)timezone_dealloc, /* tp_dealloc */ + timezone_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)timezone_repr, /* tp_repr */ + timezone_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)timezone_hash, /* tp_hash */ + timezone_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)timezone_str, /* tp_str */ + timezone_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -4458,7 +4467,7 @@ static PyTypeObject PyDateTime_TimeZoneType = { timezone_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - (richcmpfunc)timezone_richcompare,/* tp_richcompare */ + timezone_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ From 25dbe3875dc8af4d693db6d48900c7f562da39a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:51:28 +0100 Subject: [PATCH 06/12] fix UBSan failures for `PyDateTime_Time` --- Modules/_datetimemodule.c | 95 +++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 797b7b28aaf4b1..7ed31d2f0340ca 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4509,50 +4509,56 @@ look_up_timezone(PyObject *offset, PyObject *name) */ static PyObject * -time_hour(PyDateTime_Time *self, void *unused) +time_hour(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); return PyLong_FromLong(TIME_GET_HOUR(self)); } static PyObject * -time_minute(PyDateTime_Time *self, void *unused) +time_minute(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); return PyLong_FromLong(TIME_GET_MINUTE(self)); } /* The name time_second conflicted with some platform header file. */ static PyObject * -py_time_second(PyDateTime_Time *self, void *unused) +py_time_second(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); return PyLong_FromLong(TIME_GET_SECOND(self)); } static PyObject * -time_microsecond(PyDateTime_Time *self, void *unused) +time_microsecond(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); return PyLong_FromLong(TIME_GET_MICROSECOND(self)); } static PyObject * -time_tzinfo(PyDateTime_Time *self, void *unused) +time_tzinfo(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; return Py_NewRef(result); } static PyObject * -time_fold(PyDateTime_Time *self, void *unused) +time_fold(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_Time *self = _PyTime_CAST(op); return PyLong_FromLong(TIME_GET_FOLD(self)); } static PyGetSetDef time_getset[] = { - {"hour", (getter)time_hour}, - {"minute", (getter)time_minute}, - {"second", (getter)py_time_second}, - {"microsecond", (getter)time_microsecond}, - {"tzinfo", (getter)time_tzinfo}, - {"fold", (getter)time_fold}, + {"hour", time_hour}, + {"minute", time_minute}, + {"second", py_time_second}, + {"microsecond", time_microsecond}, + {"tzinfo", time_tzinfo}, + {"fold", time_fold}, {NULL} }; @@ -4677,12 +4683,13 @@ time_strptime(PyObject *cls, PyObject *args) */ static void -time_dealloc(PyDateTime_Time *self) +time_dealloc(PyObject *op) { + PyDateTime_Time *self = _PyTime_CAST(op); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free(self); } /* @@ -4691,17 +4698,20 @@ time_dealloc(PyDateTime_Time *self) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -time_utcoffset(PyObject *self, PyObject *unused) { +time_utcoffset(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_Time *self = _PyTime_CAST(op); return call_utcoffset(GET_TIME_TZINFO(self), Py_None); } static PyObject * -time_dst(PyObject *self, PyObject *unused) { +time_dst(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_Time *self = _PyTime_CAST(op); return call_dst(GET_TIME_TZINFO(self), Py_None); } static PyObject * -time_tzname(PyDateTime_Time *self, PyObject *unused) { +time_tzname(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_Time *self = _PyTime_CAST(op); return call_tzname(GET_TIME_TZINFO(self), Py_None); } @@ -4710,8 +4720,9 @@ time_tzname(PyDateTime_Time *self, PyObject *unused) { */ static PyObject * -time_repr(PyDateTime_Time *self) +time_repr(PyObject *op) { + PyDateTime_Time *self = _PyTime_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; int h = TIME_GET_HOUR(self); int m = TIME_GET_MINUTE(self); @@ -4736,17 +4747,19 @@ time_repr(PyDateTime_Time *self) } static PyObject * -time_str(PyDateTime_Time *self) +time_str(PyObject *op) { - return PyObject_CallMethodNoArgs((PyObject *)self, &_Py_ID(isoformat)); + return PyObject_CallMethodNoArgs(op, &_Py_ID(isoformat)); } static PyObject * -time_isoformat(PyDateTime_Time *self, PyObject *args, PyObject *kw) +time_isoformat(PyObject *op, PyObject *args, PyObject *kw) { char buf[100]; const char *timespec = NULL; static char *keywords[] = {"timespec", NULL}; + PyDateTime_Time *self = _PyTime_CAST(op); + PyObject *result; int us = TIME_GET_MICROSECOND(self); static const char *specs[][2] = { @@ -4807,12 +4820,13 @@ time_isoformat(PyDateTime_Time *self, PyObject *args, PyObject *kw) } static PyObject * -time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw) +time_strftime(PyObject *op, PyObject *args, PyObject *kw) { PyObject *result; PyObject *tuple; PyObject *format; static char *keywords[] = {"format", NULL}; + PyDateTime_Time *self = _PyTime_CAST(op); if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, &format)) @@ -4913,8 +4927,9 @@ time_richcompare(PyObject *self, PyObject *other, int op) } static Py_hash_t -time_hash(PyDateTime_Time *self) +time_hash(PyObject *op) { + PyDateTime_Time *self = _PyTime_CAST(op); if (self->hashcode == -1) { PyObject *offset, *self0; if (TIME_GET_FOLD(self)) { @@ -5090,18 +5105,20 @@ time_getstate(PyDateTime_Time *self, int proto) } static PyObject * -time_reduce_ex(PyDateTime_Time *self, PyObject *args) +time_reduce_ex(PyObject *op, PyObject *args) { int proto; if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) return NULL; + PyDateTime_Time *self = _PyTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto)); } static PyObject * -time_reduce(PyDateTime_Time *self, PyObject *arg) +time_reduce(PyObject *op, PyObject *Py_UNUSED(arg)) { + PyDateTime_Time *self = _PyTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2)); } @@ -5109,14 +5126,14 @@ static PyMethodDef time_methods[] = { /* Class method: */ - {"strptime", (PyCFunction)time_strptime, + {"strptime", time_strptime, METH_VARARGS | METH_CLASS, PyDoc_STR("string, format -> new time parsed from a string " "(like time.strptime()).")}, /* Instance methods: */ - {"isoformat", _PyCFunction_CAST(time_isoformat), METH_VARARGS | METH_KEYWORDS, + {"isoformat", _PyCFunction_CAST(time_isoformat), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Return string in ISO 8601 format, [HH[:MM[:SS[.mmm[uuu]]]]]" "[+HH:MM].\n\n" "The optional argument timespec specifies the number " @@ -5124,19 +5141,19 @@ static PyMethodDef time_methods[] = { "options are 'auto', 'hours', 'minutes',\n'seconds', " "'milliseconds' and 'microseconds'.\n")}, - {"strftime", _PyCFunction_CAST(time_strftime), METH_VARARGS | METH_KEYWORDS, + {"strftime", _PyCFunction_CAST(time_strftime), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("format -> strftime() style string.")}, - {"__format__", (PyCFunction)date_format, METH_VARARGS, + {"__format__", date_format, METH_VARARGS, PyDoc_STR("Formats self with strftime.")}, - {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS, + {"utcoffset", time_utcoffset, METH_NOARGS, PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, - {"tzname", (PyCFunction)time_tzname, METH_NOARGS, + {"tzname", time_tzname, METH_NOARGS, PyDoc_STR("Return self.tzinfo.tzname(self).")}, - {"dst", (PyCFunction)time_dst, METH_NOARGS, + {"dst", time_dst, METH_NOARGS, PyDoc_STR("Return self.tzinfo.dst(self).")}, DATETIME_TIME_REPLACE_METHODDEF @@ -5144,13 +5161,13 @@ static PyMethodDef time_methods[] = { {"__replace__", _PyCFunction_CAST(datetime_time_replace), METH_FASTCALL | METH_KEYWORDS, PyDoc_STR("__replace__($self, /, **changes)\n--\n\nThe same as replace().")}, - {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS, + {"fromisoformat", time_fromisoformat, METH_O | METH_CLASS, PyDoc_STR("string -> time from a string in ISO 8601 format")}, - {"__reduce_ex__", (PyCFunction)time_reduce_ex, METH_VARARGS, + {"__reduce_ex__", time_reduce_ex, METH_VARARGS, PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")}, - {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS, + {"__reduce__", time_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, {NULL, NULL} @@ -5167,18 +5184,18 @@ static PyTypeObject PyDateTime_TimeType = { "datetime.time", /* tp_name */ sizeof(PyDateTime_Time), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)time_dealloc, /* tp_dealloc */ + time_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)time_repr, /* tp_repr */ + time_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)time_hash, /* tp_hash */ + time_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)time_str, /* tp_str */ + time_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From 0a3cb0e455b3ae32bfb159508df4db0b105a4419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 13:01:17 +0100 Subject: [PATCH 07/12] fix UBSan failures for `PyDateTime_DateTime` --- Modules/_datetimemodule.c | 158 ++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 67 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 7ed31d2f0340ca..2dcfc41ec6890b 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5230,49 +5230,55 @@ static PyTypeObject PyDateTime_TimeType = { */ static PyObject * -datetime_hour(PyDateTime_DateTime *self, void *unused) +datetime_hour(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_HOUR(self)); } static PyObject * -datetime_minute(PyDateTime_DateTime *self, void *unused) +datetime_minute(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_MINUTE(self)); } static PyObject * -datetime_second(PyDateTime_DateTime *self, void *unused) +datetime_second(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_SECOND(self)); } static PyObject * -datetime_microsecond(PyDateTime_DateTime *self, void *unused) +datetime_microsecond(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_MICROSECOND(self)); } static PyObject * -datetime_tzinfo(PyDateTime_DateTime *self, void *unused) +datetime_tzinfo(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; return Py_NewRef(result); } static PyObject * -datetime_fold(PyDateTime_DateTime *self, void *unused) +datetime_fold(PyObject *op, void *Py_UNUSED(closure)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_FOLD(self)); } static PyGetSetDef datetime_getset[] = { - {"hour", (getter)datetime_hour}, - {"minute", (getter)datetime_minute}, - {"second", (getter)datetime_second}, - {"microsecond", (getter)datetime_microsecond}, - {"tzinfo", (getter)datetime_tzinfo}, - {"fold", (getter)datetime_fold}, + {"hour", datetime_hour}, + {"minute", datetime_minute}, + {"second", datetime_second}, + {"microsecond", datetime_microsecond}, + {"tzinfo", datetime_tzinfo}, + {"fold", datetime_fold}, {NULL} }; @@ -5975,12 +5981,13 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) */ static void -datetime_dealloc(PyDateTime_DateTime *self) +datetime_dealloc(PyObject *op) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free(self); } /* @@ -5989,18 +5996,21 @@ datetime_dealloc(PyDateTime_DateTime *self) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -datetime_utcoffset(PyObject *self, PyObject *unused) { - return call_utcoffset(GET_DT_TZINFO(self), self); +datetime_utcoffset(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return call_utcoffset(GET_DT_TZINFO(self), op); } static PyObject * -datetime_dst(PyObject *self, PyObject *unused) { - return call_dst(GET_DT_TZINFO(self), self); +datetime_dst(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return call_dst(GET_DT_TZINFO(self), op); } static PyObject * -datetime_tzname(PyObject *self, PyObject *unused) { - return call_tzname(GET_DT_TZINFO(self), self); +datetime_tzname(PyObject *op, PyObject *Py_UNUSED(unused)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return call_tzname(GET_DT_TZINFO(self), op); } /* @@ -6148,8 +6158,9 @@ datetime_subtract(PyObject *left, PyObject *right) /* Various ways to turn a datetime into a string. */ static PyObject * -datetime_repr(PyDateTime_DateTime *self) +datetime_repr(PyObject *op) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; PyObject *baserepr; @@ -6185,25 +6196,26 @@ datetime_repr(PyDateTime_DateTime *self) } static PyObject * -datetime_str(PyDateTime_DateTime *self) +datetime_str(PyObject *op) { PyObject *space = PyUnicode_FromString(" "); if (space == NULL) { return NULL; } - PyObject *res = PyObject_CallMethodOneArg((PyObject *)self, - &_Py_ID(isoformat), space); + PyObject *res = PyObject_CallMethodOneArg(op, &_Py_ID(isoformat), space); Py_DECREF(space); return res; } static PyObject * -datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) +datetime_isoformat(PyObject *op, PyObject *args, PyObject *kw) { int sep = 'T'; char *timespec = NULL; static char *keywords[] = {"sep", "timespec", NULL}; char buffer[100]; + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyObject *result = NULL; int us = DATE_GET_MICROSECOND(self); static const char *specs[][2] = { @@ -6255,8 +6267,7 @@ datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) return result; /* We need to append the UTC offset. */ - if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo, - (PyObject *)self) < 0) { + if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo, op) < 0) { Py_DECREF(result); return NULL; } @@ -6265,9 +6276,10 @@ datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) } static PyObject * -datetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_ctime(PyObject *op, PyObject *Py_UNUSED(ignored)) { - return format_ctime((PyObject *)self, + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return format_ctime(op, DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self)); @@ -6421,8 +6433,9 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) } static Py_hash_t -datetime_hash(PyDateTime_DateTime *self) +datetime_hash(PyObject *op) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); if (self->hashcode == -1) { PyObject *offset, *self0; if (DATE_GET_FOLD(self)) { @@ -6645,9 +6658,10 @@ local_timezone_from_local(PyDateTime_DateTime *local_dt) return local_timezone_from_timestamp(timestamp); } -static PyDateTime_DateTime * -datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) +static PyObject * +datetime_astimezone(PyObject *op, PyObject *args, PyObject *kw) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); PyDateTime_DateTime *result; PyObject *offset; PyObject *temp; @@ -6674,7 +6688,7 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) /* Conversion to self's own time zone is a NOP. */ if (self_tzinfo == tzinfo) { Py_DECREF(self_tzinfo); - return (PyDateTime_DateTime*)Py_NewRef(self); + return Py_NewRef(self); } /* Convert self to UTC. */ @@ -6739,18 +6753,19 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) PyObject_CallMethodOneArg(tzinfo, &_Py_ID(fromutc), temp); Py_DECREF(temp); - return result; + return (PyObject *)result; } static PyObject * -datetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_timetuple(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); int dstflag = -1; if (HASTZINFO(self) && self->tzinfo != Py_None) { PyObject * dst; - dst = call_dst(self->tzinfo, (PyObject *)self); + dst = call_dst(self->tzinfo, op); if (dst == NULL) return NULL; @@ -6818,8 +6833,9 @@ local_to_seconds(int year, int month, int day, #define EPOCH_SECONDS (719163LL * 24 * 60 * 60) static PyObject * -datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); PyObject *result; if (HASTZINFO(self) && self->tzinfo != Py_None) { @@ -6827,7 +6843,7 @@ datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) datetime_state *st = GET_CURRENT_STATE(current_mod); PyObject *delta; - delta = datetime_subtract((PyObject *)self, CONST_EPOCH(st)); + delta = datetime_subtract(op, CONST_EPOCH(st)); RELEASE_CURRENT_STATE(st, current_mod); if (delta == NULL) return NULL; @@ -6852,16 +6868,18 @@ datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_getdate(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_getdate(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_date(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); } static PyObject * -datetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_gettime(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self), @@ -6871,8 +6889,9 @@ datetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_gettimetz(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self), @@ -6882,11 +6901,12 @@ datetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_utctimetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) +datetime_utctimetuple(PyObject *op, PyObject *Py_UNUSED(ignored)) { int y, m, d, hh, mm, ss; PyObject *tzinfo; PyDateTime_DateTime *utcself; + PyDateTime_DateTime *self = _PyDateTime_CAST(op); tzinfo = GET_DT_TZINFO(self); if (tzinfo == Py_None) { @@ -6949,19 +6969,23 @@ datetime_getstate(PyDateTime_DateTime *self, int proto) } static PyObject * -datetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args) +datetime_reduce_ex(PyObject *op, PyObject *args) { int proto; if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) return NULL; - return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto)); + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return Py_BuildValue("(ON)", Py_TYPE(self), + datetime_getstate(self, proto)); } static PyObject * -datetime_reduce(PyDateTime_DateTime *self, PyObject *arg) +datetime_reduce(PyObject *op, PyObject *Py_UNUSED(arg)) { - return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2)); + PyDateTime_DateTime *self = _PyDateTime_CAST(op); + return Py_BuildValue("(ON)", Py_TYPE(self), + datetime_getstate(self, 2)); } static PyMethodDef datetime_methods[] = { @@ -6970,7 +6994,7 @@ static PyMethodDef datetime_methods[] = { DATETIME_DATETIME_NOW_METHODDEF - {"utcnow", (PyCFunction)datetime_utcnow, + {"utcnow", datetime_utcnow, METH_NOARGS | METH_CLASS, PyDoc_STR("Return a new datetime representing UTC day and time.")}, @@ -6978,11 +7002,11 @@ static PyMethodDef datetime_methods[] = { METH_VARARGS | METH_KEYWORDS | METH_CLASS, PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")}, - {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, + {"utcfromtimestamp", datetime_utcfromtimestamp, METH_VARARGS | METH_CLASS, PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp.")}, - {"strptime", (PyCFunction)datetime_strptime, + {"strptime", datetime_strptime, METH_VARARGS | METH_CLASS, PyDoc_STR("string, format -> new datetime parsed from a string " "(like time.strptime()).")}, @@ -6991,34 +7015,34 @@ static PyMethodDef datetime_methods[] = { METH_VARARGS | METH_KEYWORDS | METH_CLASS, PyDoc_STR("date, time -> datetime with same date and time fields")}, - {"fromisoformat", (PyCFunction)datetime_fromisoformat, + {"fromisoformat", datetime_fromisoformat, METH_O | METH_CLASS, PyDoc_STR("string -> datetime from a string in most ISO 8601 formats")}, /* Instance methods: */ - {"date", (PyCFunction)datetime_getdate, METH_NOARGS, + {"date", datetime_getdate, METH_NOARGS, PyDoc_STR("Return date object with same year, month and day.")}, - {"time", (PyCFunction)datetime_gettime, METH_NOARGS, + {"time", datetime_gettime, METH_NOARGS, PyDoc_STR("Return time object with same time but with tzinfo=None.")}, - {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS, + {"timetz", datetime_gettimetz, METH_NOARGS, PyDoc_STR("Return time object with same time and tzinfo.")}, - {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS, + {"ctime", datetime_ctime, METH_NOARGS, PyDoc_STR("Return ctime() style string.")}, - {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS, + {"timetuple", datetime_timetuple, METH_NOARGS, PyDoc_STR("Return time tuple, compatible with time.localtime().")}, - {"timestamp", (PyCFunction)datetime_timestamp, METH_NOARGS, + {"timestamp", datetime_timestamp, METH_NOARGS, PyDoc_STR("Return POSIX timestamp as float.")}, - {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS, + {"utctimetuple", datetime_utctimetuple, METH_NOARGS, PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")}, - {"isoformat", _PyCFunction_CAST(datetime_isoformat), METH_VARARGS | METH_KEYWORDS, + {"isoformat", _PyCFunction_CAST(datetime_isoformat), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("[sep] -> string in ISO 8601 format, " "YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM].\n" "sep is used to separate the year from the time, and " @@ -7028,13 +7052,13 @@ static PyMethodDef datetime_methods[] = { "options are 'auto', 'hours', 'minutes',\n'seconds', " "'milliseconds' and 'microseconds'.\n")}, - {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS, + {"utcoffset", datetime_utcoffset, METH_NOARGS, PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, - {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS, + {"tzname", datetime_tzname, METH_NOARGS, PyDoc_STR("Return self.tzinfo.tzname(self).")}, - {"dst", (PyCFunction)datetime_dst, METH_NOARGS, + {"dst", datetime_dst, METH_NOARGS, PyDoc_STR("Return self.tzinfo.dst(self).")}, DATETIME_DATETIME_REPLACE_METHODDEF @@ -7045,10 +7069,10 @@ static PyMethodDef datetime_methods[] = { {"astimezone", _PyCFunction_CAST(datetime_astimezone), METH_VARARGS | METH_KEYWORDS, PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, - {"__reduce_ex__", (PyCFunction)datetime_reduce_ex, METH_VARARGS, + {"__reduce_ex__", datetime_reduce_ex, METH_VARARGS, PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")}, - {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS, + {"__reduce__", datetime_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, {NULL, NULL} @@ -7078,18 +7102,18 @@ static PyTypeObject PyDateTime_DateTimeType = { "datetime.datetime", /* tp_name */ sizeof(PyDateTime_DateTime), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)datetime_dealloc, /* tp_dealloc */ + datetime_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)datetime_repr, /* tp_repr */ + datetime_repr, /* tp_repr */ &datetime_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)datetime_hash, /* tp_hash */ + datetime_hash, /* tp_hash */ 0, /* tp_call */ - (reprfunc)datetime_str, /* tp_str */ + datetime_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ From 19bc7e1420c44378876837f50c8490ff3d1b4458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 26 Jan 2025 13:16:14 +0100 Subject: [PATCH 08/12] fix UBSan failures for `PyDateTime_IsoCalendarDate` --- Modules/_datetimemodule.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 2dcfc41ec6890b..bb070b8882effc 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3611,17 +3611,17 @@ typedef struct { } PyDateTime_IsoCalendarDate; static PyObject * -iso_calendar_date_repr(PyDateTime_IsoCalendarDate *self) +iso_calendar_date_repr(PyObject *self) { - PyObject* year = PyTuple_GetItem((PyObject *)self, 0); + PyObject *year = PyTuple_GetItem(self, 0); if (year == NULL) { return NULL; } - PyObject* week = PyTuple_GetItem((PyObject *)self, 1); + PyObject *week = PyTuple_GetItem(self, 1); if (week == NULL) { return NULL; } - PyObject* weekday = PyTuple_GetItem((PyObject *)self, 2); + PyObject *weekday = PyTuple_GetItem(self, 2); if (weekday == NULL) { return NULL; } @@ -3634,7 +3634,7 @@ static PyObject * iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { // Construct the tuple that this reduces to - PyObject * reduce_tuple = Py_BuildValue( + PyObject *reduce_tuple = Py_BuildValue( "O((OOO))", &PyTuple_Type, PyTuple_GET_ITEM(self, 0), PyTuple_GET_ITEM(self, 1), @@ -3645,9 +3645,9 @@ iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -iso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused) +iso_calendar_date_year(PyObject *self, void *unused) { - PyObject *year = PyTuple_GetItem((PyObject *)self, 0); + PyObject *year = PyTuple_GetItem(self, 0); if (year == NULL) { return NULL; } @@ -3655,9 +3655,9 @@ iso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused) } static PyObject * -iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused) +iso_calendar_date_week(PyObject *self, void *unused) { - PyObject *week = PyTuple_GetItem((PyObject *)self, 1); + PyObject *week = PyTuple_GetItem(self, 1); if (week == NULL) { return NULL; } @@ -3665,9 +3665,9 @@ iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused) } static PyObject * -iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused) +iso_calendar_date_weekday(PyObject *self, void *unused) { - PyObject *weekday = PyTuple_GetItem((PyObject *)self, 2); + PyObject *weekday = PyTuple_GetItem(self, 2); if (weekday == NULL) { return NULL; } @@ -3675,31 +3675,30 @@ iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused) } static PyGetSetDef iso_calendar_date_getset[] = { - {"year", (getter)iso_calendar_date_year}, - {"week", (getter)iso_calendar_date_week}, - {"weekday", (getter)iso_calendar_date_weekday}, + {"year", iso_calendar_date_year}, + {"week", iso_calendar_date_week}, + {"weekday", iso_calendar_date_weekday}, {NULL} }; static PyMethodDef iso_calendar_date_methods[] = { - {"__reduce__", (PyCFunction)iso_calendar_date_reduce, METH_NOARGS, + {"__reduce__", iso_calendar_date_reduce, METH_NOARGS, PyDoc_STR("__reduce__() -> (cls, state)")}, {NULL, NULL}, }; static int -iso_calendar_date_traverse(PyDateTime_IsoCalendarDate *self, visitproc visit, - void *arg) +iso_calendar_date_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); - return PyTuple_Type.tp_traverse((PyObject *)self, visit, arg); + return PyTuple_Type.tp_traverse(self, visit, arg); } static void -iso_calendar_date_dealloc(PyDateTime_IsoCalendarDate *self) +iso_calendar_date_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); - PyTuple_Type.tp_dealloc((PyObject *)self); // delegate GC-untrack as well + PyTuple_Type.tp_dealloc(self); // delegate GC-untrack as well Py_DECREF(tp); } From b189115328f2a133d152ccea35b54ba7b5082d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:53:41 +0100 Subject: [PATCH 09/12] use 'dummy' for NOARGS method --- Modules/_datetimemodule.c | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index bb070b8882effc..5e86b39cce2d6d 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3256,7 +3256,7 @@ date_fromtimestamp(PyObject *cls, PyObject *obj) * generally the same as calling C's time. */ static PyObject * -date_today(PyObject *cls, PyObject *dummy) +date_today(PyObject *cls, PyObject *Py_UNUSED(dummy)) { PyObject *time; PyObject *result; @@ -3531,7 +3531,7 @@ date_repr(PyObject *op) } static PyObject * -date_isoformat(PyObject *op, PyObject *Py_UNUSED(ignored)) +date_isoformat(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Date *self = _PyDate_CAST(op); return PyUnicode_FromFormat("%04d-%02d-%02d", @@ -3547,7 +3547,7 @@ date_str(PyObject *self) static PyObject * -date_ctime(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_ctime(PyObject *self, PyObject *Py_UNUSED(dummy)) { return format_ctime(self, 0, 0, 0); } @@ -3593,7 +3593,7 @@ date_format(PyObject *self, PyObject *args) /* ISO methods. */ static PyObject * -date_isoweekday(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_isoweekday(PyObject *self, PyObject *Py_UNUSED(dummy)) { int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); @@ -3750,7 +3750,7 @@ iso_calendar_date_new_impl(PyTypeObject *type, int year, int week, } static PyObject * -date_isocalendar(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_isocalendar(PyObject *self, PyObject *Py_UNUSED(dummy)) { int year = GET_YEAR(self); int week1_monday = iso_week1_monday(year); @@ -3805,7 +3805,7 @@ date_richcompare(PyObject *self, PyObject *other, int op) } static PyObject * -date_timetuple(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_timetuple(PyObject *self, PyObject *Py_UNUSED(dummy)) { return build_struct_time(GET_YEAR(self), GET_MONTH(self), @@ -3853,14 +3853,14 @@ date_hash(PyObject *op) } static PyObject * -date_toordinal(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_toordinal(PyObject *self, PyObject *Py_UNUSED(dummy)) { return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self), GET_DAY(self))); } static PyObject * -date_weekday(PyObject *self, PyObject *Py_UNUSED(ignored)) +date_weekday(PyObject *self, PyObject *Py_UNUSED(dummy)) { int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); return PyLong_FromLong(dow); @@ -3879,7 +3879,7 @@ date_getstate(PyDateTime_Date *self) } static PyObject * -date_reduce(PyObject *op, PyObject *Py_UNUSED(ignored)) +date_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Date *self = _PyDate_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self)); @@ -4145,7 +4145,7 @@ tzinfo_fromutc(PyObject *self, PyObject *dt) */ static PyObject * -tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) +tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(dummy)) { PyObject *args, *state; PyObject *getinitargs; @@ -4411,7 +4411,7 @@ timezone_fromutc(PyObject *op, PyObject *arg) } static PyObject * -timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(ignored)) +timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); if (self->name == NULL) @@ -4697,19 +4697,19 @@ time_dealloc(PyObject *op) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -time_utcoffset(PyObject *op, PyObject *Py_UNUSED(unused)) { +time_utcoffset(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Time *self = _PyTime_CAST(op); return call_utcoffset(GET_TIME_TZINFO(self), Py_None); } static PyObject * -time_dst(PyObject *op, PyObject *Py_UNUSED(unused)) { +time_dst(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Time *self = _PyTime_CAST(op); return call_dst(GET_TIME_TZINFO(self), Py_None); } static PyObject * -time_tzname(PyObject *op, PyObject *Py_UNUSED(unused)) { +time_tzname(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Time *self = _PyTime_CAST(op); return call_tzname(GET_TIME_TZINFO(self), Py_None); } @@ -6275,7 +6275,7 @@ datetime_isoformat(PyObject *op, PyObject *args, PyObject *kw) } static PyObject * -datetime_ctime(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_ctime(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return format_ctime(op, @@ -6756,7 +6756,7 @@ datetime_astimezone(PyObject *op, PyObject *args, PyObject *kw) } static PyObject * -datetime_timetuple(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_timetuple(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); int dstflag = -1; @@ -6832,7 +6832,7 @@ local_to_seconds(int year, int month, int day, #define EPOCH_SECONDS (719163LL * 24 * 60 * 60) static PyObject * -datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); PyObject *result; @@ -6867,7 +6867,7 @@ datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_getdate(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_getdate(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_date(GET_YEAR(self), @@ -6876,7 +6876,7 @@ datetime_getdate(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_gettime(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_gettime(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), @@ -6888,7 +6888,7 @@ datetime_gettime(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_gettimetz(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_gettimetz(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), @@ -6900,7 +6900,7 @@ datetime_gettimetz(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -datetime_utctimetuple(PyObject *op, PyObject *Py_UNUSED(ignored)) +datetime_utctimetuple(PyObject *op, PyObject *Py_UNUSED(dummy)) { int y, m, d, hh, mm, ss; PyObject *tzinfo; From 3c883a68c4b0dda0a538a897eb64473466fecb50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:58:18 +0100 Subject: [PATCH 10/12] use 'dummy' for NOARGS method --- Modules/_datetimemodule.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 5e86b39cce2d6d..89e8a3374246d8 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -2978,7 +2978,7 @@ delta_getstate(PyDateTime_Delta *self) } static PyObject * -delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(closure)) +delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyObject *total_seconds; PyObject *total_microseconds; @@ -3645,7 +3645,7 @@ iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) } static PyObject * -iso_calendar_date_year(PyObject *self, void *unused) +iso_calendar_date_year(PyObject *self, void *Py_UNUSED(closure)) { PyObject *year = PyTuple_GetItem(self, 0); if (year == NULL) { @@ -3655,7 +3655,7 @@ iso_calendar_date_year(PyObject *self, void *unused) } static PyObject * -iso_calendar_date_week(PyObject *self, void *unused) +iso_calendar_date_week(PyObject *self, void *Py_UNUSED(closure)) { PyObject *week = PyTuple_GetItem(self, 1); if (week == NULL) { @@ -3665,7 +3665,7 @@ iso_calendar_date_week(PyObject *self, void *unused) } static PyObject * -iso_calendar_date_weekday(PyObject *self, void *unused) +iso_calendar_date_weekday(PyObject *self, void *Py_UNUSED(closure)) { PyObject *weekday = PyTuple_GetItem(self, 2); if (weekday == NULL) { @@ -5115,7 +5115,7 @@ time_reduce_ex(PyObject *op, PyObject *args) } static PyObject * -time_reduce(PyObject *op, PyObject *Py_UNUSED(arg)) +time_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Time *self = _PyTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2)); @@ -5995,19 +5995,19 @@ datetime_dealloc(PyObject *op) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * -datetime_utcoffset(PyObject *op, PyObject *Py_UNUSED(unused)) { +datetime_utcoffset(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return call_utcoffset(GET_DT_TZINFO(self), op); } static PyObject * -datetime_dst(PyObject *op, PyObject *Py_UNUSED(unused)) { +datetime_dst(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return call_dst(GET_DT_TZINFO(self), op); } static PyObject * -datetime_tzname(PyObject *op, PyObject *Py_UNUSED(unused)) { +datetime_tzname(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_DateTime *self = _PyDateTime_CAST(op); return call_tzname(GET_DT_TZINFO(self), op); } From 22bdf8c59e74cd5d028e591399b2b98041e78db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:26:38 +0100 Subject: [PATCH 11/12] Fixup naming --- Modules/_datetimemodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9a9216e4e5e518..3a32e9e0788b79 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -2998,7 +2998,7 @@ delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy)) } static PyObject * -delta_reduce(PyObject *op, PyObject *Py_UNUSED(closure)) +delta_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyDateTime_Delta *self = _PyDelta_CAST(op); return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self)); From b6ee734cc1f43a698eb7780e0d61473925d833ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 8 Feb 2025 09:52:58 +0100 Subject: [PATCH 12/12] Do not use `_` + capital letter in new code as it is also UB. --- Modules/_datetimemodule.c | 136 +++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9a9216e4e5e518..476a891ca75c78 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -76,30 +76,30 @@ typedef struct { #define TIMEZONE_TYPE(st) &PyDateTime_TimeZoneType #define ISOCALENDAR_DATE_TYPE(st) st->isocalendar_date_type -#define _PyDate_CAST(op) ((PyDateTime_Date *)(op)) +#define PyDate_CAST(op) ((PyDateTime_Date *)(op)) #define PyDate_Check(op) PyObject_TypeCheck(op, DATE_TYPE(NO_STATE)) #define PyDate_CheckExact(op) Py_IS_TYPE(op, DATE_TYPE(NO_STATE)) -#define _PyDateTime_CAST(op) ((PyDateTime_DateTime *)(op)) +#define PyDateTime_CAST(op) ((PyDateTime_DateTime *)(op)) #define PyDateTime_Check(op) PyObject_TypeCheck(op, DATETIME_TYPE(NO_STATE)) #define PyDateTime_CheckExact(op) Py_IS_TYPE(op, DATETIME_TYPE(NO_STATE)) -#define _PyTime_CAST(op) ((PyDateTime_Time *)(op)) +#define PyTime_CAST(op) ((PyDateTime_Time *)(op)) #define PyTime_Check(op) PyObject_TypeCheck(op, TIME_TYPE(NO_STATE)) #define PyTime_CheckExact(op) Py_IS_TYPE(op, TIME_TYPE(NO_STATE)) -#define _PyDelta_CAST(op) ((PyDateTime_Delta *)(op)) +#define PyDelta_CAST(op) ((PyDateTime_Delta *)(op)) #define PyDelta_Check(op) PyObject_TypeCheck(op, DELTA_TYPE(NO_STATE)) #define PyDelta_CheckExact(op) Py_IS_TYPE(op, DELTA_TYPE(NO_STATE)) -#define _PyTZInfo_CAST(op) ((PyDateTime_TZInfo *)(op)) +#define PyTZInfo_CAST(op) ((PyDateTime_TZInfo *)(op)) #define PyTZInfo_Check(op) PyObject_TypeCheck(op, TZINFO_TYPE(NO_STATE)) #define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, TZINFO_TYPE(NO_STATE)) -#define _PyTimeZone_CAST(op) ((PyDateTime_TimeZone *)(op)) +#define PyTimeZone_CAST(op) ((PyDateTime_TimeZone *)(op)) #define PyTimezone_Check(op) PyObject_TypeCheck(op, TIMEZONE_TYPE(NO_STATE)) -#define _PyIsoCalendarDate_CAST(op) ((PyDateTime_IsoCalendarDate *)(op)) +#define PyIsoCalendarDate_CAST(op) ((PyDateTime_IsoCalendarDate *)(op)) #define CONST_US_PER_MS(st) st->us_per_ms #define CONST_US_PER_SECOND(st) st->us_per_second @@ -309,9 +309,9 @@ clear_current_module(PyInterpreterState *interp, PyObject *expected) #define TIME_SET_FOLD(o, v) (PyDateTime_TIME_GET_FOLD(o) = (v)) /* Delta accessors for timedelta. */ -#define GET_TD_DAYS(o) (_PyDelta_CAST(o)->days) -#define GET_TD_SECONDS(o) (_PyDelta_CAST(o)->seconds) -#define GET_TD_MICROSECONDS(o) (_PyDelta_CAST(o)->microseconds) +#define GET_TD_DAYS(o) (PyDelta_CAST(o)->days) +#define GET_TD_SECONDS(o) (PyDelta_CAST(o)->seconds) +#define GET_TD_MICROSECONDS(o) (PyDelta_CAST(o)->microseconds) #define SET_TD_DAYS(o, v) ((o)->days = (v)) #define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) @@ -2517,7 +2517,7 @@ static PyObject *delta_getstate(PyDateTime_Delta *self); static Py_hash_t delta_hash(PyObject *op) { - PyDateTime_Delta *self = _PyDelta_CAST(op); + PyDateTime_Delta *self = PyDelta_CAST(op); if (self->hashcode == -1) { PyObject *temp = delta_getstate(self); if (temp != NULL) { @@ -2983,7 +2983,7 @@ delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy)) PyObject *total_seconds; PyObject *total_microseconds; - total_microseconds = delta_to_microseconds(_PyDelta_CAST(op)); + total_microseconds = delta_to_microseconds(PyDelta_CAST(op)); if (total_microseconds == NULL) return NULL; @@ -3000,7 +3000,7 @@ delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * delta_reduce(PyObject *op, PyObject *Py_UNUSED(closure)) { - PyDateTime_Delta *self = _PyDelta_CAST(op); + PyDateTime_Delta *self = PyDelta_CAST(op); return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self)); } @@ -3142,21 +3142,21 @@ look_up_delta(int days, int seconds, int microseconds, PyTypeObject *type) static PyObject * date_year(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return PyLong_FromLong(GET_YEAR(self)); } static PyObject * date_month(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return PyLong_FromLong(GET_MONTH(self)); } static PyObject * date_day(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return PyLong_FromLong(GET_DAY(self)); } @@ -3524,7 +3524,7 @@ date_subtract(PyObject *left, PyObject *right) static PyObject * date_repr(PyObject *op) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return PyUnicode_FromFormat("%s(%d, %d, %d)", Py_TYPE(self)->tp_name, GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); @@ -3533,7 +3533,7 @@ date_repr(PyObject *op) static PyObject * date_isoformat(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return PyUnicode_FromFormat("%04d-%02d-%02d", GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); } @@ -3843,7 +3843,7 @@ static PyObject *date_getstate(PyDateTime_Date *self); static Py_hash_t date_hash(PyObject *op) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); if (self->hashcode == -1) { self->hashcode = generic_hash( (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE); @@ -3881,7 +3881,7 @@ date_getstate(PyDateTime_Date *self) static PyObject * date_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Date *self = _PyDate_CAST(op); + PyDateTime_Date *self = PyDate_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self)); } @@ -4256,7 +4256,7 @@ timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw) static void timezone_dealloc(PyObject *op) { - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); Py_CLEAR(self->offset); Py_CLEAR(self->name); Py_TYPE(self)->tp_free(self); @@ -4270,15 +4270,15 @@ timezone_richcompare(PyObject *self, PyObject *other, int op) if (!PyTimezone_Check(other)) { Py_RETURN_NOTIMPLEMENTED; } - PyDateTime_TimeZone *lhs = _PyTimeZone_CAST(self); - PyDateTime_TimeZone *rhs = _PyTimeZone_CAST(other); + PyDateTime_TimeZone *lhs = PyTimeZone_CAST(self); + PyDateTime_TimeZone *rhs = PyTimeZone_CAST(other); return delta_richcompare(lhs->offset, rhs->offset, op); } static Py_hash_t timezone_hash(PyObject *op) { - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); return delta_hash(self->offset); } @@ -4301,7 +4301,7 @@ timezone_repr(PyObject *op) { /* Note that although timezone is not subclassable, it is convenient to use Py_TYPE(self)->tp_name here. */ - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; if (op == CONST_UTC(NO_STATE)) { @@ -4318,7 +4318,7 @@ timezone_repr(PyObject *op) static PyObject * timezone_str(PyObject *op) { - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); int hours, minutes, seconds, microseconds; PyObject *offset; char sign; @@ -4377,7 +4377,7 @@ timezone_utcoffset(PyObject *op, PyObject *dt) if (_timezone_check_argument(dt, "utcoffset") == -1) return NULL; - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); return Py_NewRef(self->offset); } @@ -4406,14 +4406,14 @@ timezone_fromutc(PyObject *op, PyObject *arg) return NULL; } - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); } static PyObject * timezone_getinitargs(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_TimeZone *self = _PyTimeZone_CAST(op); + PyDateTime_TimeZone *self = PyTimeZone_CAST(op); if (self->name == NULL) return PyTuple_Pack(1, self->offset); return PyTuple_Pack(2, self->offset, self->name); @@ -4510,14 +4510,14 @@ look_up_timezone(PyObject *offset, PyObject *name) static PyObject * time_hour(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return PyLong_FromLong(TIME_GET_HOUR(self)); } static PyObject * time_minute(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return PyLong_FromLong(TIME_GET_MINUTE(self)); } @@ -4525,21 +4525,21 @@ time_minute(PyObject *op, void *Py_UNUSED(closure)) static PyObject * py_time_second(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return PyLong_FromLong(TIME_GET_SECOND(self)); } static PyObject * time_microsecond(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return PyLong_FromLong(TIME_GET_MICROSECOND(self)); } static PyObject * time_tzinfo(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; return Py_NewRef(result); } @@ -4547,7 +4547,7 @@ time_tzinfo(PyObject *op, void *Py_UNUSED(closure)) static PyObject * time_fold(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return PyLong_FromLong(TIME_GET_FOLD(self)); } @@ -4684,7 +4684,7 @@ time_strptime(PyObject *cls, PyObject *args) static void time_dealloc(PyObject *op) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } @@ -4698,19 +4698,19 @@ time_dealloc(PyObject *op) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * time_utcoffset(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return call_utcoffset(GET_TIME_TZINFO(self), Py_None); } static PyObject * time_dst(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return call_dst(GET_TIME_TZINFO(self), Py_None); } static PyObject * time_tzname(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return call_tzname(GET_TIME_TZINFO(self), Py_None); } @@ -4721,7 +4721,7 @@ time_tzname(PyObject *op, PyObject *Py_UNUSED(dummy)) { static PyObject * time_repr(PyObject *op) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; int h = TIME_GET_HOUR(self); int m = TIME_GET_MINUTE(self); @@ -4757,7 +4757,7 @@ time_isoformat(PyObject *op, PyObject *args, PyObject *kw) char buf[100]; const char *timespec = NULL; static char *keywords[] = {"timespec", NULL}; - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); PyObject *result; int us = TIME_GET_MICROSECOND(self); @@ -4825,7 +4825,7 @@ time_strftime(PyObject *op, PyObject *args, PyObject *kw) PyObject *tuple; PyObject *format; static char *keywords[] = {"format", NULL}; - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, &format)) @@ -4928,7 +4928,7 @@ time_richcompare(PyObject *self, PyObject *other, int op) static Py_hash_t time_hash(PyObject *op) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); if (self->hashcode == -1) { PyObject *offset, *self0; if (TIME_GET_FOLD(self)) { @@ -5110,14 +5110,14 @@ time_reduce_ex(PyObject *op, PyObject *args) if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) return NULL; - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto)); } static PyObject * time_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_Time *self = _PyTime_CAST(op); + PyDateTime_Time *self = PyTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2)); } @@ -5231,35 +5231,35 @@ static PyTypeObject PyDateTime_TimeType = { static PyObject * datetime_hour(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_HOUR(self)); } static PyObject * datetime_minute(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_MINUTE(self)); } static PyObject * datetime_second(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_SECOND(self)); } static PyObject * datetime_microsecond(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_MICROSECOND(self)); } static PyObject * datetime_tzinfo(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; return Py_NewRef(result); } @@ -5267,7 +5267,7 @@ datetime_tzinfo(PyObject *op, void *Py_UNUSED(closure)) static PyObject * datetime_fold(PyObject *op, void *Py_UNUSED(closure)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return PyLong_FromLong(DATE_GET_FOLD(self)); } @@ -5982,7 +5982,7 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) static void datetime_dealloc(PyObject *op) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); if (HASTZINFO(self)) { Py_XDECREF(self->tzinfo); } @@ -5996,19 +5996,19 @@ datetime_dealloc(PyObject *op) /* These are all METH_NOARGS, so don't need to check the arglist. */ static PyObject * datetime_utcoffset(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return call_utcoffset(GET_DT_TZINFO(self), op); } static PyObject * datetime_dst(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return call_dst(GET_DT_TZINFO(self), op); } static PyObject * datetime_tzname(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return call_tzname(GET_DT_TZINFO(self), op); } @@ -6159,7 +6159,7 @@ datetime_subtract(PyObject *left, PyObject *right) static PyObject * datetime_repr(PyObject *op) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); const char *type_name = Py_TYPE(self)->tp_name; PyObject *baserepr; @@ -6213,7 +6213,7 @@ datetime_isoformat(PyObject *op, PyObject *args, PyObject *kw) char *timespec = NULL; static char *keywords[] = {"sep", "timespec", NULL}; char buffer[100]; - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); PyObject *result = NULL; int us = DATE_GET_MICROSECOND(self); @@ -6277,7 +6277,7 @@ datetime_isoformat(PyObject *op, PyObject *args, PyObject *kw) static PyObject * datetime_ctime(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return format_ctime(op, DATE_GET_HOUR(self), DATE_GET_MINUTE(self), @@ -6434,7 +6434,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) static Py_hash_t datetime_hash(PyObject *op) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); if (self->hashcode == -1) { PyObject *offset, *self0; if (DATE_GET_FOLD(self)) { @@ -6660,7 +6660,7 @@ local_timezone_from_local(PyDateTime_DateTime *local_dt) static PyObject * datetime_astimezone(PyObject *op, PyObject *args, PyObject *kw) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); PyDateTime_DateTime *result; PyObject *offset; PyObject *temp; @@ -6758,7 +6758,7 @@ datetime_astimezone(PyObject *op, PyObject *args, PyObject *kw) static PyObject * datetime_timetuple(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); int dstflag = -1; if (HASTZINFO(self) && self->tzinfo != Py_None) { @@ -6834,7 +6834,7 @@ local_to_seconds(int year, int month, int day, static PyObject * datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); PyObject *result; if (HASTZINFO(self) && self->tzinfo != Py_None) { @@ -6869,7 +6869,7 @@ datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * datetime_getdate(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return new_date(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); @@ -6878,7 +6878,7 @@ datetime_getdate(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * datetime_gettime(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self), @@ -6890,7 +6890,7 @@ datetime_gettime(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * datetime_gettimetz(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return new_time(DATE_GET_HOUR(self), DATE_GET_MINUTE(self), DATE_GET_SECOND(self), @@ -6905,7 +6905,7 @@ datetime_utctimetuple(PyObject *op, PyObject *Py_UNUSED(dummy)) int y, m, d, hh, mm, ss; PyObject *tzinfo; PyDateTime_DateTime *utcself; - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); tzinfo = GET_DT_TZINFO(self); if (tzinfo == Py_None) { @@ -6974,7 +6974,7 @@ datetime_reduce_ex(PyObject *op, PyObject *args) if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) return NULL; - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto)); } @@ -6982,7 +6982,7 @@ datetime_reduce_ex(PyObject *op, PyObject *args) static PyObject * datetime_reduce(PyObject *op, PyObject *Py_UNUSED(arg)) { - PyDateTime_DateTime *self = _PyDateTime_CAST(op); + PyDateTime_DateTime *self = PyDateTime_CAST(op); return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2)); }