diff options
author | Hai Shi <shihai1992@gmail.com> | 2021-01-06 19:47:19 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-06 19:47:19 (GMT) |
commit | 1ab045933b90d1954af983cc08d1bf0bc46b6240 (patch) | |
tree | c4b1942afc384291bbd51ddaaaed9833b5e41932 /Modules | |
parent | f22b7ca1afd98a7381a9fe9e53bd6dfa2a5eba16 (diff) | |
download | cpython-1ab045933b90d1954af983cc08d1bf0bc46b6240.zip cpython-1ab045933b90d1954af983cc08d1bf0bc46b6240.tar.gz cpython-1ab045933b90d1954af983cc08d1bf0bc46b6240.tar.bz2 |
bpo-41798: Allocate the _datetime.datetime_CAPI on the heap memory (GH-24096)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_datetimemodule.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index c3e0b52..8ef2dad 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -6473,26 +6473,44 @@ 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(void) +{ + PyDateTime_CAPI *capi = PyMem_Malloc(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; + // 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; +} + +static void +datetime_destructor(PyObject *op) +{ + void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); + PyMem_Free(ptr); +} static int _datetime_exec(PyObject *module) @@ -6581,7 +6599,6 @@ _datetime_exec(PyObject *module) } PyDateTime_TimeZone_UTC = x; - 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 +6636,13 @@ _datetime_exec(PyObject *module) return -1; } - x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); + 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); return -1; } |