From: Moshe Zadka Date: Sat, 31 Mar 2001 15:44:16 +0000 (+0000) Subject: Backported pyexpat memory-leak plugs X-Git-Tag: v2.0.1c1~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aafd60c9bc8153c6497e454378c39a30f808f963;p=thirdparty%2FPython%2Fcpython.git Backported pyexpat memory-leak plugs backported by Martin van Lowis --- diff --git a/Misc/NEWS b/Misc/NEWS index fd7ca7da5bbf..ed83f987976f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -153,6 +153,8 @@ http://sourceforge.net/tracker/index.php?func=detail&aid=&group_id=5470&atid - distutils/command/install.py - make .get_outputs() produce a list of unique filenames +- pyexpat.c - removed memory leaks + What's New in Python 2.0? ========================= diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index 543648bf9d42..6c85f352ca44 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -5,6 +5,13 @@ #include "xmlparse.h" #endif +#ifndef PyGC_HEAD_SIZE +#define PyGC_HEAD_SIZE 0 +#define PyObject_GC_Init(x) +#define PyObject_GC_Fini(m) +#define Py_TPFLAGS_GC 0 +#endif + enum HandlerTypes { StartElement, EndElement, @@ -75,6 +82,7 @@ conv_atts_using_string(XML_Char **atts) } if (PyDict_SetItemString(attrs_obj, (char*)*attrs_k, rv) < 0) { + Py_DECREF(rv); Py_DECREF(attrs_obj); attrs_obj = NULL; goto finally; @@ -198,12 +206,12 @@ conv_string_len_to_utf8(const XML_Char *str, int len) /* Callback routines */ -static void clear_handlers(xmlparseobject *self); +static void clear_handlers(xmlparseobject *self, int decref); static void flag_error(xmlparseobject *self) { - clear_handlers(self); + clear_handlers(self, 1); } #define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ @@ -500,6 +508,13 @@ xmlparse_ParseFile(xmlparseobject *self, PyObject *args) if (!rv || bytes_read == 0) break; } + if (rv == 0) { + PyErr_Format(ErrorObject, "%.200s: line %i, column %i", + XML_ErrorString(XML_GetErrorCode(self->itself)), + XML_GetErrorLineNumber(self->itself), + XML_GetErrorColumnNumber(self->itself)); + return NULL; + } return Py_BuildValue("i", rv); } @@ -568,10 +583,13 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) #endif new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, - encoding); - if (!new_parser) { - Py_DECREF(new_parser); - return PyErr_NoMemory(); + encoding); + new_parser->handlers = 0; + PyObject_GC_Init(new_parser); + + if (!new_parser->itself) { + Py_DECREF(new_parser); + return PyErr_NoMemory(); } XML_SetUserData(new_parser->itself, (void *)new_parser); @@ -581,7 +599,11 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) /* do nothing */; new_parser->handlers = malloc(sizeof(PyObject *)*i); - clear_handlers(new_parser); + if (!new_parser->handlers) { + Py_DECREF(new_parser); + return PyErr_NoMemory(); + } + clear_handlers(new_parser, 0); /* then copy handlers from self */ for (i = 0; handler_info[i].name != NULL; i++) { @@ -615,7 +637,7 @@ static struct PyMethodDef xmlparse_methods[] = { /* ---------- */ -static xmlparseobject * +static PyObject * newxmlparseobject(char *encoding, char *namespace_separator) { int i; @@ -635,12 +657,14 @@ newxmlparseobject(char *encoding, char *namespace_separator) self->returns_unicode = 1; #endif + self->handlers = NULL; if (namespace_separator) { self->itself = XML_ParserCreateNS(encoding, *namespace_separator); } else{ self->itself = XML_ParserCreate(encoding); } + PyObject_GC_Init(self); if (self->itself == NULL) { PyErr_SetString(PyExc_RuntimeError, "XML_ParserCreate failed"); @@ -653,9 +677,13 @@ newxmlparseobject(char *encoding, char *namespace_separator) /* do nothing */; self->handlers = malloc(sizeof(PyObject *)*i); - clear_handlers(self); + if (!self->handlers){ + Py_DECREF(self); + return PyErr_NoMemory(); + } + clear_handlers(self, 0); - return self; + return (PyObject*)self; } @@ -663,12 +691,16 @@ static void xmlparse_dealloc(xmlparseobject *self) { int i; + PyObject_GC_Fini(self); if (self->itself) XML_ParserFree(self->itself); self->itself = NULL; - for (i=0; handler_info[i].name != NULL; i++) { - Py_XDECREF(self->handlers[i]); + if(self->handlers){ + for (i=0; handler_info[i].name != NULL; i++) { + Py_XDECREF(self->handlers[i]); + } + free (self->handlers); } #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 /* Code for versions before 1.6 */ @@ -780,6 +812,29 @@ xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v) return -1; } +#ifdef WITH_CYCLE_GC +static int +xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) +{ + int i, err; + for (i = 0; handler_info[i].name != NULL; i++) { + if (!op->handlers[i]) + continue; + err = visit(op->handlers[i], arg); + if (err) + return err; + } + return 0; +} + +static int +xmlparse_clear(xmlparseobject *op) +{ + clear_handlers(op, 1); + return 0; +} +#endif + static char Xmlparsetype__doc__[] = "XML parser"; @@ -787,7 +842,7 @@ static PyTypeObject Xmlparsetype = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "xmlparser", /*tp_name*/ - sizeof(xmlparseobject), /*tp_basicsize*/ + sizeof(xmlparseobject) + PyGC_HEAD_SIZE,/*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)xmlparse_dealloc, /*tp_dealloc*/ @@ -802,10 +857,17 @@ static PyTypeObject Xmlparsetype = { (hashfunc)0, /*tp_hash*/ (ternaryfunc)0, /*tp_call*/ (reprfunc)0, /*tp_str*/ - - /* Space for future expansion */ - 0L,0L,0L,0L, - Xmlparsetype__doc__ /* Documentation string */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/ + Xmlparsetype__doc__, /* Documentation string */ +#ifdef WITH_CYCLE_GC + (traverseproc)xmlparse_traverse, /* tp_traverse */ + (inquiry)xmlparse_clear /* tp_clear */ +#else + 0, 0 +#endif }; /* End of code for xmlparser objects */ @@ -968,14 +1030,17 @@ initpyexpat(void) } static void -clear_handlers(xmlparseobject *self) +clear_handlers(xmlparseobject *self, int decref) { - int i = 0; - - for (; handler_info[i].name!=NULL; i++) { - self->handlers[i]=NULL; - handler_info[i].setter(self->itself, NULL); - } + int i = 0; + + for (; handler_info[i].name!=NULL; i++) { + if (decref){ + Py_XDECREF(self->handlers[i]); + } + self->handlers[i]=NULL; + handler_info[i].setter(self->itself, NULL); + } } typedef void (*pairsetter)(XML_Parser, void *handler1, void *handler2);