From 5312f2f8298d19c0785160b76fcb6dc707dcb33d Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Mon, 4 Jan 2021 19:06:04 +0800 Subject: [PATCH 1/4] Allocate the datetime.datetime_CAPI on the heap memory. --- Modules/_datetimemodule.c | 62 ++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index c3e0b52baa6fac..7aaf041ae3b4fe 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6473,30 +6473,49 @@ static PyMethodDef module_methods[] = { {NULL, NULL} }; -/* C API. Clients get at this via PyDateTime_IMPORT, defined in - * datetime.h. +/* Get a new C API by calling this function. + * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h. */ -static PyDateTime_CAPI CAPI = { - &PyDateTime_DateType, - &PyDateTime_DateTimeType, - &PyDateTime_TimeType, - &PyDateTime_DeltaType, - &PyDateTime_TZInfoType, - NULL, // PyDatetime_TimeZone_UTC not initialized yet - new_date_ex, - new_datetime_ex, - new_time_ex, - new_delta_ex, - new_timezone, - datetime_fromtimestamp, - datetime_date_fromtimestamp_capi, - new_datetime_ex2, - new_time_ex2 -}; +static inline PyDateTime_CAPI * +get_datetime_capi() +{ + PyDateTime_CAPI *capi = PyMem_Calloc(1, sizeof(PyDateTime_CAPI)); + if (capi == NULL) { + PyErr_NoMemory(); + return NULL; + } + capi->DateType = &PyDateTime_DateType; + capi->DateTimeType = &PyDateTime_DateTimeType; + capi->TimeType = &PyDateTime_TimeType; + capi->DeltaType = &PyDateTime_DeltaType; + capi->TZInfoType = &PyDateTime_TZInfoType; + capi->Date_FromDate = new_date_ex; + capi->DateTime_FromDateAndTime = new_datetime_ex; + capi->Time_FromTime = new_time_ex; + capi->Delta_FromDelta = new_delta_ex; + capi->TimeZone_FromTimeZone = new_timezone; + capi->DateTime_FromTimestamp = datetime_fromtimestamp; + capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; + capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; + capi->Time_FromTimeAndFold = new_time_ex2; + return capi; +} + +static void +datetime_destructor(PyObject *op) +{ + void *p = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); + PyMem_Free(p); +} static int _datetime_exec(PyObject *module) { + PyDateTime_CAPI *CAPI = get_datetime_capi(); + if (CAPI == NULL) { + return -1; + } + // `&...` is not a constant expression according to a strict reading // of C standards. Fill tp_base at run-time rather than statically. // See https://bugs.python.org/issue40777 @@ -6581,7 +6600,7 @@ _datetime_exec(PyObject *module) } PyDateTime_TimeZone_UTC = x; - CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; + CAPI->TimeZone_UTC = PyDateTime_TimeZone_UTC; /* bpo-37642: These attributes are rounded to the nearest minute for backwards * compatibility, even though the constructor will accept a wider range of @@ -6619,8 +6638,9 @@ _datetime_exec(PyObject *module) return -1; } - x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); + x = PyCapsule_New(CAPI, PyDateTime_CAPSULE_NAME, datetime_destructor); if (x == NULL) { + PyMem_Free(CAPI); return -1; } From 4aa5a09b41b009bc0b7dcb22f91563ff7d3e9329 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 5 Jan 2021 19:28:08 +0800 Subject: [PATCH 2/4] apply victor's comment --- Modules/_datetimemodule.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 7aaf041ae3b4fe..15b06ee1c70605 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6477,9 +6477,9 @@ static PyMethodDef module_methods[] = { * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h. */ static inline PyDateTime_CAPI * -get_datetime_capi() +get_datetime_capi(void) { - PyDateTime_CAPI *capi = PyMem_Calloc(1, sizeof(PyDateTime_CAPI)); + PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI)); if (capi == NULL) { PyErr_NoMemory(); return NULL; @@ -6498,6 +6498,10 @@ get_datetime_capi() capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; capi->Time_FromTimeAndFold = new_time_ex2; + // Make sure this function is called after PyDateTime_TimeZone_UTC has + // been initialized. + assert(PyDateTime_TimeZone_UTC != NULL); + capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref return capi; } @@ -6511,11 +6515,6 @@ datetime_destructor(PyObject *op) static int _datetime_exec(PyObject *module) { - PyDateTime_CAPI *CAPI = get_datetime_capi(); - if (CAPI == NULL) { - return -1; - } - // `&...` is not a constant expression according to a strict reading // of C standards. Fill tp_base at run-time rather than statically. // See https://bugs.python.org/issue40777 @@ -6600,13 +6599,17 @@ _datetime_exec(PyObject *module) } PyDateTime_TimeZone_UTC = x; - CAPI->TimeZone_UTC = PyDateTime_TimeZone_UTC; + PyDateTime_CAPI *capi = get_datetime_capi(); + if (capi == NULL) { + return -1; + } /* bpo-37642: These attributes are rounded to the nearest minute for backwards * compatibility, even though the constructor will accept a wider range of * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) { + PyMem_Free(capi); return -1; } @@ -6616,6 +6619,7 @@ _datetime_exec(PyObject *module) delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ if (delta == NULL) { + PyMem_Free(capi); return -1; } @@ -6627,25 +6631,29 @@ _datetime_exec(PyObject *module) PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, PyDateTime_TimeZone_UTC, 0); if (PyDateTime_Epoch == NULL) { + PyMem_Free(capi); return -1; } /* module initialization */ if (PyModule_AddIntMacro(module, MINYEAR) < 0) { + PyMem_Free(capi); return -1; } if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { + PyMem_Free(capi); return -1; } - x = PyCapsule_New(CAPI, PyDateTime_CAPSULE_NAME, datetime_destructor); + x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); if (x == NULL) { - PyMem_Free(CAPI); + PyMem_Free(capi); return -1; } if (PyModule_AddObject(module, "datetime_CAPI", x) < 0) { Py_DECREF(x); + PyMem_Free(capi); return -1; } @@ -6673,6 +6681,7 @@ _datetime_exec(PyObject *module) seconds_per_day = PyLong_FromLong(24 * 3600); if (us_per_ms == NULL || us_per_second == NULL || us_per_minute == NULL || seconds_per_day == NULL) { + PyMem_Free(capi); return -1; } @@ -6683,6 +6692,7 @@ _datetime_exec(PyObject *module) us_per_day = PyLong_FromDouble(86400000000.0); us_per_week = PyLong_FromDouble(604800000000.0); if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { + PyMem_Free(capi); return -1; } return 0; From 4696be9c5fa3079764283b2dd7a8d803f5bfe09c Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 6 Jan 2021 00:47:46 +0800 Subject: [PATCH 3/4] apply petr's comment --- Modules/_datetimemodule.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 15b06ee1c70605..c6afee27053ab3 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6653,7 +6653,6 @@ _datetime_exec(PyObject *module) if (PyModule_AddObject(module, "datetime_CAPI", x) < 0) { Py_DECREF(x); - PyMem_Free(capi); return -1; } @@ -6681,7 +6680,6 @@ _datetime_exec(PyObject *module) seconds_per_day = PyLong_FromLong(24 * 3600); if (us_per_ms == NULL || us_per_second == NULL || us_per_minute == NULL || seconds_per_day == NULL) { - PyMem_Free(capi); return -1; } @@ -6692,7 +6690,6 @@ _datetime_exec(PyObject *module) us_per_day = PyLong_FromDouble(86400000000.0); us_per_week = PyLong_FromDouble(604800000000.0); if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { - PyMem_Free(capi); return -1; } return 0; From 7eebfb199164b68f1e0bd43e2dbaae5785d1aeba Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 6 Jan 2021 22:40:25 +0800 Subject: [PATCH 4/4] apply victor's comment --- Modules/_datetimemodule.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index c6afee27053ab3..8ef2dad37a3a05 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6508,8 +6508,8 @@ get_datetime_capi(void) static void datetime_destructor(PyObject *op) { - void *p = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); - PyMem_Free(p); + void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); + PyMem_Free(ptr); } static int @@ -6599,17 +6599,12 @@ _datetime_exec(PyObject *module) } PyDateTime_TimeZone_UTC = x; - PyDateTime_CAPI *capi = get_datetime_capi(); - if (capi == NULL) { - return -1; - } /* bpo-37642: These attributes are rounded to the nearest minute for backwards * compatibility, even though the constructor will accept a wider range of * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ if (delta == NULL) { - PyMem_Free(capi); return -1; } @@ -6619,7 +6614,6 @@ _datetime_exec(PyObject *module) delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ if (delta == NULL) { - PyMem_Free(capi); return -1; } @@ -6631,20 +6625,21 @@ _datetime_exec(PyObject *module) PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, PyDateTime_TimeZone_UTC, 0); if (PyDateTime_Epoch == NULL) { - PyMem_Free(capi); return -1; } /* module initialization */ if (PyModule_AddIntMacro(module, MINYEAR) < 0) { - PyMem_Free(capi); return -1; } if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { - PyMem_Free(capi); return -1; } + PyDateTime_CAPI *capi = get_datetime_capi(); + if (capi == NULL) { + return -1; + } x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); if (x == NULL) { PyMem_Free(capi);