Kaydet (Commit) aafd60c9 authored tarafından Moshe Zadka's avatar Moshe Zadka

Backported pyexpat memory-leak plugs

backported by Martin van Lowis
üst bf9183ee
...@@ -153,6 +153,8 @@ http://sourceforge.net/tracker/index.php?func=detail&aid=<id>&group_id=5470&atid ...@@ -153,6 +153,8 @@ http://sourceforge.net/tracker/index.php?func=detail&aid=<id>&group_id=5470&atid
- distutils/command/install.py - make .get_outputs() produce a list of unique - distutils/command/install.py - make .get_outputs() produce a list of unique
filenames filenames
- pyexpat.c - removed memory leaks
What's New in Python 2.0? What's New in Python 2.0?
========================= =========================
......
...@@ -5,6 +5,13 @@ ...@@ -5,6 +5,13 @@
#include "xmlparse.h" #include "xmlparse.h"
#endif #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 { enum HandlerTypes {
StartElement, StartElement,
EndElement, EndElement,
...@@ -75,6 +82,7 @@ conv_atts_using_string(XML_Char **atts) ...@@ -75,6 +82,7 @@ conv_atts_using_string(XML_Char **atts)
} }
if (PyDict_SetItemString(attrs_obj, if (PyDict_SetItemString(attrs_obj,
(char*)*attrs_k, rv) < 0) { (char*)*attrs_k, rv) < 0) {
Py_DECREF(rv);
Py_DECREF(attrs_obj); Py_DECREF(attrs_obj);
attrs_obj = NULL; attrs_obj = NULL;
goto finally; goto finally;
...@@ -198,12 +206,12 @@ conv_string_len_to_utf8(const XML_Char *str, int len) ...@@ -198,12 +206,12 @@ conv_string_len_to_utf8(const XML_Char *str, int len)
/* Callback routines */ /* Callback routines */
static void clear_handlers(xmlparseobject *self); static void clear_handlers(xmlparseobject *self, int decref);
static void static void
flag_error(xmlparseobject *self) flag_error(xmlparseobject *self)
{ {
clear_handlers(self); clear_handlers(self, 1);
} }
#define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ #define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \
...@@ -500,6 +508,13 @@ xmlparse_ParseFile(xmlparseobject *self, PyObject *args) ...@@ -500,6 +508,13 @@ xmlparse_ParseFile(xmlparseobject *self, PyObject *args)
if (!rv || bytes_read == 0) if (!rv || bytes_read == 0)
break; 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); return Py_BuildValue("i", rv);
} }
...@@ -568,10 +583,13 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) ...@@ -568,10 +583,13 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args)
#endif #endif
new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context,
encoding); encoding);
if (!new_parser) { new_parser->handlers = 0;
Py_DECREF(new_parser); PyObject_GC_Init(new_parser);
return PyErr_NoMemory();
if (!new_parser->itself) {
Py_DECREF(new_parser);
return PyErr_NoMemory();
} }
XML_SetUserData(new_parser->itself, (void *)new_parser); XML_SetUserData(new_parser->itself, (void *)new_parser);
...@@ -581,7 +599,11 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) ...@@ -581,7 +599,11 @@ xmlparse_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args)
/* do nothing */; /* do nothing */;
new_parser->handlers = malloc(sizeof(PyObject *)*i); 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 */ /* then copy handlers from self */
for (i = 0; handler_info[i].name != NULL; i++) { for (i = 0; handler_info[i].name != NULL; i++) {
...@@ -615,7 +637,7 @@ static struct PyMethodDef xmlparse_methods[] = { ...@@ -615,7 +637,7 @@ static struct PyMethodDef xmlparse_methods[] = {
/* ---------- */ /* ---------- */
static xmlparseobject * static PyObject *
newxmlparseobject(char *encoding, char *namespace_separator) newxmlparseobject(char *encoding, char *namespace_separator)
{ {
int i; int i;
...@@ -635,12 +657,14 @@ newxmlparseobject(char *encoding, char *namespace_separator) ...@@ -635,12 +657,14 @@ newxmlparseobject(char *encoding, char *namespace_separator)
self->returns_unicode = 1; self->returns_unicode = 1;
#endif #endif
self->handlers = NULL;
if (namespace_separator) { if (namespace_separator) {
self->itself = XML_ParserCreateNS(encoding, *namespace_separator); self->itself = XML_ParserCreateNS(encoding, *namespace_separator);
} }
else{ else{
self->itself = XML_ParserCreate(encoding); self->itself = XML_ParserCreate(encoding);
} }
PyObject_GC_Init(self);
if (self->itself == NULL) { if (self->itself == NULL) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"XML_ParserCreate failed"); "XML_ParserCreate failed");
...@@ -653,9 +677,13 @@ newxmlparseobject(char *encoding, char *namespace_separator) ...@@ -653,9 +677,13 @@ newxmlparseobject(char *encoding, char *namespace_separator)
/* do nothing */; /* do nothing */;
self->handlers = malloc(sizeof(PyObject *)*i); 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 ...@@ -663,12 +691,16 @@ static void
xmlparse_dealloc(xmlparseobject *self) xmlparse_dealloc(xmlparseobject *self)
{ {
int i; int i;
PyObject_GC_Fini(self);
if (self->itself) if (self->itself)
XML_ParserFree(self->itself); XML_ParserFree(self->itself);
self->itself = NULL; self->itself = NULL;
for (i=0; handler_info[i].name != NULL; i++) { if(self->handlers){
Py_XDECREF(self->handlers[i]); 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 #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6
/* Code for versions before 1.6 */ /* Code for versions before 1.6 */
...@@ -780,6 +812,29 @@ xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v) ...@@ -780,6 +812,29 @@ xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v)
return -1; 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__[] = static char Xmlparsetype__doc__[] =
"XML parser"; "XML parser";
...@@ -787,7 +842,7 @@ static PyTypeObject Xmlparsetype = { ...@@ -787,7 +842,7 @@ static PyTypeObject Xmlparsetype = {
PyObject_HEAD_INIT(NULL) PyObject_HEAD_INIT(NULL)
0, /*ob_size*/ 0, /*ob_size*/
"xmlparser", /*tp_name*/ "xmlparser", /*tp_name*/
sizeof(xmlparseobject), /*tp_basicsize*/ sizeof(xmlparseobject) + PyGC_HEAD_SIZE,/*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
/* methods */ /* methods */
(destructor)xmlparse_dealloc, /*tp_dealloc*/ (destructor)xmlparse_dealloc, /*tp_dealloc*/
...@@ -802,10 +857,17 @@ static PyTypeObject Xmlparsetype = { ...@@ -802,10 +857,17 @@ static PyTypeObject Xmlparsetype = {
(hashfunc)0, /*tp_hash*/ (hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/ (ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/ (reprfunc)0, /*tp_str*/
0, /* tp_getattro */
/* Space for future expansion */ 0, /* tp_setattro */
0L,0L,0L,0L, 0, /* tp_as_buffer */
Xmlparsetype__doc__ /* Documentation string */ 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 */ /* End of code for xmlparser objects */
...@@ -968,14 +1030,17 @@ initpyexpat(void) ...@@ -968,14 +1030,17 @@ initpyexpat(void)
} }
static void static void
clear_handlers(xmlparseobject *self) clear_handlers(xmlparseobject *self, int decref)
{ {
int i = 0; int i = 0;
for (; handler_info[i].name!=NULL; i++) { for (; handler_info[i].name!=NULL; i++) {
self->handlers[i]=NULL; if (decref){
handler_info[i].setter(self->itself, NULL); 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); typedef void (*pairsetter)(XML_Parser, void *handler1, void *handler2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment