summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorHai Shi <shihai1992@gmail.com>2021-01-06 19:47:19 (GMT)
committerGitHub <noreply@github.com>2021-01-06 19:47:19 (GMT)
commit1ab045933b90d1954af983cc08d1bf0bc46b6240 (patch)
treec4b1942afc384291bbd51ddaaaed9833b5e41932 /Modules
parentf22b7ca1afd98a7381a9fe9e53bd6dfa2a5eba16 (diff)
downloadcpython-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.c64
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;
}