Applied patch for bug #596931: XML_ParseReset and memory leaks.

This commit is contained in:
Karl Waclawek 2002-08-21 20:00:09 +00:00
parent f5f615c931
commit de7c8418bb
2 changed files with 104 additions and 28 deletions

View 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;

View 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 *