]> granicus.if.org Git - libexpat/commitdiff
Applied patch for bug #596931: XML_ParseReset and memory leaks.
authorKarl Waclawek <kwaclaw@users.sourceforge.net>
Wed, 21 Aug 2002 20:00:09 +0000 (20:00 +0000)
committerKarl Waclawek <kwaclaw@users.sourceforge.net>
Wed, 21 Aug 2002 20:00:09 +0000 (20:00 +0000)
expat/lib/expat.h
expat/lib/xmlparse.c

index 44c08581c726589383c00829b1f0c28c6555656c..04830052391edd6b5b17f0b684d0f8b3c1b573f1 100644 (file)
@@ -190,11 +190,12 @@ XML_ParserCreate_MM(const XML_Char *encoding,
 /* Prepare a parser object to be re-used.  This is particularly
    valuable when memory allocation overhead is disproportionatly high,
    such as when a large number of small documnents need to be parsed.
-   All handlers are cleared from the parser.
+   All handlers are cleared from the parser, except for the 
+   unknownEncodingHandler.
 
    Added in Expat 1.95.3.
 */
-XMLPARSEAPI(int)
+XMLPARSEAPI(XML_Bool)
 XML_ParserReset(XML_Parser parser, const XML_Char *encoding);
 
 /* atts is array of name/value pairs, terminated by 0;
index e6393ef64adc9e9bb4964cf61e47e852bec050b1..8242eedbc413a0a3ab78f376941b95f8d6834e1a 100644 (file)
@@ -339,6 +339,7 @@ static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
 static void normalizePublicId(XML_Char *s);
 static void dtdInit(DTD *, XML_Parser parser);
 
+static void dtdReset(DTD *, XML_Parser parser); /* do not call if parentParser != NULL */
 static void dtdDestroy(DTD *, XML_Parser parser);
 
 static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser);
@@ -354,6 +355,7 @@ static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
 
 static void hashTableInit(HASH_TABLE *, XML_Memory_Handling_Suite *ms);
 
+static void hashTableClear(HASH_TABLE *);
 static void hashTableDestroy(HASH_TABLE *);
 static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
 static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
@@ -379,7 +381,7 @@ static ELEMENT_TYPE * getElementType(XML_Parser Paraser,
                                      const char *ptr,
                                      const char *end);
 
-static XML_Bool parserInit(XML_Parser parser, const XML_Char *encodingName);
+static void parserInit(XML_Parser parser, const XML_Char *encodingName);
 
 #define poolStart(pool) ((pool)->start)
 #define poolEnd(pool) ((pool)->ptr)
@@ -661,18 +663,26 @@ XML_ParserCreate_MM(const XML_Char *encodingName,
     return NULL;
   }
   dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+
   freeBindingList = NULL;
-  inheritedBindings = NULL;
   freeTagList = NULL;
 
+  groupSize = 0;
+  groupConnector = NULL;
+
+  unknownEncodingHandler = NULL;
+  unknownEncodingHandlerData = NULL;
+
   namespaceSeparator = '!';
   ns = XML_FALSE;
   ns_triplets = XML_FALSE;
+
+  parserInit(parser, encodingName);
+  dtdInit(&dtd, parser);
   poolInit(&tempPool, &(((Parser *) parser)->m_mem));
   poolInit(&temp2Pool, &(((Parser *) parser)->m_mem));
 
-  if (!parserInit(parser, encodingName) || !atts
-      || !dataBuf || (encodingName && !protocolEncodingName)) {
+  if (!atts || !dataBuf || (encodingName && !protocolEncodingName)) {
     XML_ParserFree(parser);
     return NULL;
   }
@@ -694,7 +704,7 @@ XML_ParserCreate_MM(const XML_Char *encodingName,
   return parser;
 }
 
-static XML_Bool
+static void
 parserInit(XML_Parser parser, const XML_Char *encodingName)
 {
   processor = prologInitProcessor;
@@ -724,7 +734,6 @@ parserInit(XML_Parser parser, const XML_Char *encodingName)
   externalEntityRefHandler = NULL;
   externalEntityRefHandlerArg = parser;
   skippedEntityHandler = NULL;
-  unknownEncodingHandler = NULL;
   elementDeclHandler = NULL;
   attlistDeclHandler = NULL;
   entityDeclHandler = NULL;
@@ -752,33 +761,56 @@ parserInit(XML_Parser parser, const XML_Char *encodingName)
   openInternalEntities = 0;
   defaultExpandInternalEntities = XML_TRUE;
   tagLevel = 0;
-  tagStack = 0;
+  tagStack = NULL;
+  inheritedBindings = NULL;
   nSpecifiedAtts = 0;
-  groupSize = 0;
-  groupConnector = NULL;
   unknownEncodingMem = NULL;
   unknownEncodingRelease = NULL;
   unknownEncodingData = NULL;
-  unknownEncodingHandlerData = NULL;
   parentParser = NULL;
 #ifdef XML_DTD
   isParamEntity = XML_FALSE;
   paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
 #endif
-  dtdInit(&dtd, parser);
-  return XML_TRUE;
 }
 
-int
+/* moves list of bindings to freeBindingList */
+void moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
+{
+  while (bindings) {
+    BINDING *b = bindings;
+    bindings = bindings->nextTagBinding;
+    b->nextTagBinding = freeBindingList;
+    freeBindingList = b;
+  }
+}
+
+XML_Bool
 XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
 {
-  if (parentParser) return 0;
-#ifdef XML_DTD
-  if (dtd.scaffold) dtdDestroy(&dtd, parser);
-#endif
+  TAG *tStk;
+  if (parentParser) 
+    return XML_FALSE;
+  /* move tagStack to freeTagList */
+  tStk = tagStack;
+  while (tStk) {
+    TAG *tag = tStk;
+    tStk = tStk->parent;
+    tag->parent = freeTagList;
+    moveToFreeBindingList(parser, tag->bindings);
+    tag->bindings = NULL;
+    freeTagList = tag;
+  }
+  moveToFreeBindingList(parser, inheritedBindings);
+  if (unknownEncodingMem)
+    FREE(unknownEncodingMem);
+  if (unknownEncodingRelease)
+    unknownEncodingRelease(unknownEncodingData);
+  parserInit(parser, encodingName);
+  dtdReset(&dtd, parser);
   poolClear(&tempPool);
   poolClear(&temp2Pool);
-  return parserInit(parser, encodingName);
+  return XML_TRUE;
 }
 
 int
@@ -1260,10 +1292,10 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
     XmlUpdatePosition(encoding, positionPtr, end, &position);
     nLeftOver = s + len - end;
     if (nLeftOver) {
-      if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+      if (buffer == NULL || nLeftOver > bufferLim - buffer) {
         /* FIXME avoid integer overflow */
         char *temp;
-        temp = buffer == 0 ? MALLOC(len * 2) : REALLOC(buffer, len * 2);
+        temp = buffer == NULL ? MALLOC(len * 2) : REALLOC(buffer, len * 2);
         if (temp == NULL) {
           errorCode = XML_ERROR_NO_MEMORY;
           return XML_STATUS_ERROR;
@@ -4617,6 +4649,39 @@ dtdSwap(DTD *p1, DTD *p2)
 
 #endif /* XML_DTD */
 
+static void
+dtdReset(DTD *p, XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+  hashTableIterInit(&iter, &(p->elementTypes));
+  for (;;) {
+    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+    if (!e)
+      break;
+    if (e->allocDefaultAtts != 0)
+      FREE(e->defaultAtts);
+  }
+  hashTableClear(&(p->generalEntities));
+#ifdef XML_DTD
+  hashTableClear(&(p->paramEntities));
+#endif /* XML_DTD */
+  hashTableClear(&(p->elementTypes));
+  hashTableClear(&(p->attributeIds));
+  hashTableClear(&(p->prefixes));
+  poolClear(&(p->pool));
+#ifdef XML_DTD
+  poolClear(&(p->entityValuePool));
+#endif /* XML_DTD */
+  if (p->scaffIndex) {
+    FREE(p->scaffIndex);
+    p->scaffIndex = NULL;
+  }
+  if (p->scaffold) {
+    FREE(p->scaffold);
+    p->scaffold = NULL;
+  }
+}
+
 static void
 dtdDestroy(DTD *p, XML_Parser parser)
 {
@@ -4932,6 +4997,21 @@ lookup(HASH_TABLE *table, KEY name, size_t createSize)
   return table->v[i];
 }
 
+static void
+hashTableClear(HASH_TABLE *table)
+{
+  size_t i;
+  for (i = 0; i < table->size; i++) {
+    NAMED *p = table->v[i];
+    if (p) {
+      table->mem->free_fcn(p);
+      table->v[i] = NULL;
+    }
+  }
+  table->usedLim = table->size / 2;
+  table->used = 0;
+}
+
 static void
 hashTableDestroy(HASH_TABLE *table)
 {
@@ -4951,7 +5031,7 @@ hashTableInit(HASH_TABLE *p, XML_Memory_Handling_Suite *ms)
   p->size = 0;
   p->usedLim = 0;
   p->used = 0;
-  p->v = 0;
+  p->v = NULL;
   p->mem = ms;
 }
 
@@ -5013,17 +5093,12 @@ poolDestroy(STRING_POOL *pool)
     pool->mem->free_fcn(p);
     p = tem;
   }
-  pool->blocks = NULL;
   p = pool->freeBlocks;
   while (p) {
     BLOCK *tem = p->next;
     pool->mem->free_fcn(p);
     p = tem;
   }
-  pool->freeBlocks = NULL;
-  pool->ptr = NULL;
-  pool->start = NULL;
-  pool->end = NULL;
 }
 
 static XML_Char *