]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Backported pyexpat memory-leak plugs
authorMoshe Zadka <moshez@math.huji.ac.il>
Sat, 31 Mar 2001 15:44:16 +0000 (15:44 +0000)
committerMoshe Zadka <moshez@math.huji.ac.il>
Sat, 31 Mar 2001 15:44:16 +0000 (15:44 +0000)
backported by Martin van Lowis

Misc/NEWS
Modules/pyexpat.c

index fd7ca7da5bbf8c62310f943a5665a64f60b43306..ed83f987976ff40797d82bfdbc9ff2c2be1e36df 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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 
                                  filenames
 
+- pyexpat.c - removed memory leaks
+
 What's New in Python 2.0?
 =========================
 
index 543648bf9d42e8d434b65926fd9c978b6f08744e..6c85f352ca440dd7e634cc555a37ccf1012a7b5f 100644 (file)
@@ -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);