From 23389bf82162fac68fc1644d23f34f0e1e340569 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sat, 2 Jan 2021 20:27:35 +0800 Subject: [PATCH 1/2] Allocate the expat_CAPI on the heap memory. --- .../2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst | 3 + Modules/pyexpat.c | 65 +++++++++++-------- 2 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst new file mode 100644 index 00000000000000..3521daba87d6f4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst @@ -0,0 +1,3 @@ +Allocate the ``expat_CAPI`` on the heap memory to avoid more module instances +hold a single ``expat_CAPI`` object after pyexpat ported to multiphase +initialization (:pep:`489`). diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 7d7da568972a2e..187c4073c7652c 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1836,6 +1836,15 @@ add_features(PyObject *mod) } #endif +static void +pyexpat_destructor(PyObject *op) +{ + void *p = PyCapsule_GetPointer(op, PyExpat_CAPSULE_NAME); + if (p != NULL) { + PyMem_Free(p); + } +} + static int pyexpat_exec(PyObject *mod) { @@ -1921,40 +1930,42 @@ pyexpat_exec(PyObject *mod) MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); #undef MYCONST - static struct PyExpat_CAPI capi; + struct PyExpat_CAPI *capi = PyMem_Calloc(1, sizeof(struct PyExpat_CAPI)); /* initialize pyexpat dispatch table */ - capi.size = sizeof(capi); - capi.magic = PyExpat_CAPI_MAGIC; - capi.MAJOR_VERSION = XML_MAJOR_VERSION; - capi.MINOR_VERSION = XML_MINOR_VERSION; - capi.MICRO_VERSION = XML_MICRO_VERSION; - capi.ErrorString = XML_ErrorString; - capi.GetErrorCode = XML_GetErrorCode; - capi.GetErrorColumnNumber = XML_GetErrorColumnNumber; - capi.GetErrorLineNumber = XML_GetErrorLineNumber; - capi.Parse = XML_Parse; - capi.ParserCreate_MM = XML_ParserCreate_MM; - capi.ParserFree = XML_ParserFree; - capi.SetCharacterDataHandler = XML_SetCharacterDataHandler; - capi.SetCommentHandler = XML_SetCommentHandler; - capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; - capi.SetElementHandler = XML_SetElementHandler; - capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; - capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; - capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; - capi.SetUserData = XML_SetUserData; - capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; - capi.SetEncoding = XML_SetEncoding; - capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; + capi->size = sizeof(*capi); + capi->magic = PyExpat_CAPI_MAGIC; + capi->MAJOR_VERSION = XML_MAJOR_VERSION; + capi->MINOR_VERSION = XML_MINOR_VERSION; + capi->MICRO_VERSION = XML_MICRO_VERSION; + capi->ErrorString = XML_ErrorString; + capi->GetErrorCode = XML_GetErrorCode; + capi->GetErrorColumnNumber = XML_GetErrorColumnNumber; + capi->GetErrorLineNumber = XML_GetErrorLineNumber; + capi->Parse = XML_Parse; + capi->ParserCreate_MM = XML_ParserCreate_MM; + capi->ParserFree = XML_ParserFree; + capi->SetCharacterDataHandler = XML_SetCharacterDataHandler; + capi->SetCommentHandler = XML_SetCommentHandler; + capi->SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; + capi->SetElementHandler = XML_SetElementHandler; + capi->SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; + capi->SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; + capi->SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; + capi->SetUserData = XML_SetUserData; + capi->SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; + capi->SetEncoding = XML_SetEncoding; + capi->DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; #if XML_COMBINED_VERSION >= 20100 - capi.SetHashSalt = XML_SetHashSalt; + capi->SetHashSalt = XML_SetHashSalt; #else - capi.SetHashSalt = NULL; + capi->SetHashSalt = NULL; #endif /* export using capsule */ - PyObject *capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); + PyObject *capi_object = PyCapsule_New(capi, PyExpat_CAPSULE_NAME, + pyexpat_destructor); if (capi_object == NULL) { + PyMem_Free(capi); return -1; } From 48edc5a788e871e6cf6c080c6e9bd9910950c1b3 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sun, 3 Jan 2021 22:02:25 +0800 Subject: [PATCH 2/2] apply victor's comment --- .../2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst | 3 --- Modules/pyexpat.c | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst deleted file mode 100644 index 3521daba87d6f4..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-01-02-23-32-55.bpo-41798.yZZWzQ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Allocate the ``expat_CAPI`` on the heap memory to avoid more module instances -hold a single ``expat_CAPI`` object after pyexpat ported to multiphase -initialization (:pep:`489`). diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 187c4073c7652c..0ea438ae2ae5dd 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1840,9 +1840,7 @@ static void pyexpat_destructor(PyObject *op) { void *p = PyCapsule_GetPointer(op, PyExpat_CAPSULE_NAME); - if (p != NULL) { - PyMem_Free(p); - } + PyMem_Free(p); } static int @@ -1931,6 +1929,10 @@ pyexpat_exec(PyObject *mod) #undef MYCONST struct PyExpat_CAPI *capi = PyMem_Calloc(1, sizeof(struct PyExpat_CAPI)); + if (capi == NULL) { + PyErr_NoMemory(); + return -1; + } /* initialize pyexpat dispatch table */ capi->size = sizeof(*capi); capi->magic = PyExpat_CAPI_MAGIC;