> Yes memory allocation failures should be handled, at least be reported,
> and of course not leaking or crashing. However it's really hard to
perfectly
>handle out of memory failures.
> We really need to fix leaks or crashes and report the error though the
> API, anything beyond that is nice but less critical. If the application >
chose to ignore the memory error, nothing can be done to save it anyway.
Hi,
I am attaching a patch for some memory leak fixes in malloc failure
scenarios, also adding checks where malloc return is not checked for
NULL(parser.c). Please let me know if the changes are ok.
Regards
Ashwin
*** parser.c 2008-03-28 14:05:04.000000000 +0530
--- parserleakfix.c 2008-03-29 08:45:12.000000000 +0530
*************** xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
*** 1016,1022 ****
goto mem_error;
defaults->nbAttrs = 0;
defaults->maxAttrs = 4;
! xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL);
} else if (defaults->nbAttrs >= defaults->maxAttrs) {
xmlDefAttrsPtr temp;
--- 1016,1025 ----
goto mem_error;
defaults->nbAttrs = 0;
defaults->maxAttrs = 4;
! if(xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL)
< 0){
! free(defaults);
! goto mem_error;
! }
} else if (defaults->nbAttrs >= defaults->maxAttrs) {
xmlDefAttrsPtr temp;
*************** xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
*** 1026,1032 ****
goto mem_error;
defaults = temp;
defaults->maxAttrs *= 2;
! xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL);
}
/*
--- 1029,1038 ----
goto mem_error;
defaults = temp;
defaults->maxAttrs *= 2;
! if(xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL)
< 0){
! free(defaults);
! goto mem_error;
! }
}
/*
*************** xmlNewBlanksWrapperInputStream(xmlParser
*** 2073,2078 ****
--- 2079,2085 ----
length = xmlStrlen(entity->name) + 5;
buffer = xmlMallocAtomic(length);
if (buffer == NULL) {
+ xmlFree(input);
xmlErrMemory(ctxt, NULL);
return(NULL);
}
*************** xmlParserHandlePEReference(xmlParserCtxt
*** 2289,2297 ****
#define growBuffer(buffer) { \
xmlChar *tmp; \
buffer##_size *= 2;
\
! tmp = (xmlChar *) \
! xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
! if (tmp == NULL) goto mem_error; \
buffer = tmp; \
}
--- 2296,2306 ----
#define growBuffer(buffer) { \
xmlChar *tmp; \
buffer##_size *= 2;
\
! tmp = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \
! if (tmp == NULL) { \
! xmlFree(buffer); \
! goto mem_error; \
! } \
buffer = tmp; \
}
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2321,2326 ****
--- 2330,2336 ----
int buffer_size = 0;
xmlChar *current = NULL;
+ xmlChar *rep = NULL;
const xmlChar *last;
xmlEntityPtr ent;
int c,l;
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2380,2386 ****
"predefined entity has no content\n");
}
} else if ((ent != NULL) && (ent->content != NULL)) {
! xmlChar *rep;
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
--- 2390,2396 ----
"predefined entity has no content\n");
}
} else if ((ent != NULL) && (ent->content != NULL)) {
!
ctxt->depth++;
rep = xmlStringDecodeEntities(ctxt, ent->content, what,
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2396,2401 ****
--- 2406,2412 ----
}
}
xmlFree(rep);
+ rep = NULL;
}
} else if (ent != NULL) {
int i = xmlStrlen(ent->name);
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2415,2421 ****
"String decoding PE Reference: %.30s\n", str);
ent = xmlParseStringPEReference(ctxt, &str);
if (ent != NULL) {
! xmlChar *rep;
if (ent->content == NULL) {
if (xmlLoadEntityContent(ctxt, ent) < 0) {
--- 2426,2432 ----
"String decoding PE Reference: %.30s\n", str);
ent = xmlParseStringPEReference(ctxt, &str);
if (ent != NULL) {
!
if (ent->content == NULL) {
if (xmlLoadEntityContent(ctxt, ent) < 0) {
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2435,2440 ****
--- 2446,2452 ----
}
}
xmlFree(rep);
+ rep = NULL;
}
}
} else {
*************** xmlStringLenDecodeEntities(xmlParserCtxt
*** 2453,2458 ****
--- 2465,2474 ----
return(buffer);
mem_error:
+ if (rep != NULL)
+ {
+ xmlFree(rep);
+ }
xmlErrMemory(ctxt, NULL);
return(NULL);
}
*************** xmlSplitQName(xmlParserCtxtPtr ctxt, con
*** 2634,2640 ****
tmp = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (tmp == NULL) {
! xmlFree(tmp);
xmlErrMemory(ctxt, NULL);
return(NULL);
}
--- 2650,2656 ----
tmp = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (tmp == NULL) {
! xmlFree(buffer);
xmlErrMemory(ctxt, NULL);
return(NULL);
}
*************** static xmlChar *
*** 3197,3202 ****
--- 3213,3219 ----
xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
xmlChar limit = 0;
xmlChar *buf = NULL;
+ xmlChar *rep = NULL;
int len = 0;
int buf_size = 0;
int c, l, in_space = 0;
*************** xmlParseAttValueComplex(xmlParserCtxtPtr
*** 3280,3286 ****
}
} else if ((ent != NULL) &&
(ctxt->replaceEntities != 0)) {
! xmlChar *rep;
if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
rep = xmlStringDecodeEntities(ctxt, ent->content,
--- 3297,3303 ----
}
} else if ((ent != NULL) &&
(ctxt->replaceEntities != 0)) {
!
if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
rep = xmlStringDecodeEntities(ctxt, ent->content,
*************** xmlParseAttValueComplex(xmlParserCtxtPtr
*** 3295,3300 ****
--- 3312,3318 ----
}
}
xmlFree(rep);
+ rep = NULL;
}
} else {
if (len > buf_size - 10) {
*************** xmlParseAttValueComplex(xmlParserCtxtPtr
*** 3313,3323 ****
*/
if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
(ent->content != NULL)) {
! xmlChar *rep;
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0,
0);
! if (rep != NULL)
xmlFree(rep);
}
/*
--- 3331,3343 ----
*/
if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
(ent->content != NULL)) {
!
rep = xmlStringDecodeEntities(ctxt, ent->content,
XML_SUBSTITUTE_REF, 0, 0,
0);
! if (rep != NULL){
xmlFree(rep);
+ rep = NULL;
+ }
}
/*
*************** xmlParseAttValueComplex(xmlParserCtxtPtr
*** 3375,3380 ****
--- 3395,3404 ----
return(buf);
mem_error:
+ if (rep != NULL)
+ {
+ xmlFree(rep);
+ }
xmlErrMemory(ctxt, NULL);
return(NULL);
}
*************** xmlParseEntityDecl(xmlParserCtxtPtr ctxt
*** 4644,4649 ****
--- 4668,4677 ----
(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
if (ctxt->myDoc == NULL) {
ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
+ if (ctxt->myDoc == NULL){
+ xmlErrMemory(ctxt, "New Doc failed");
+ return;
+ }
}
if (ctxt->myDoc->intSubset == NULL)
ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
*************** xmlParseEntityDecl(xmlParserCtxtPtr ctxt
*** 4712,4717 ****
--- 4740,4749 ----
(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
if (ctxt->myDoc == NULL) {
ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
+ if (ctxt->myDoc == NULL){
+ xmlErrMemory(ctxt, "New Doc failed");
+ return;
+ }
}
if (ctxt->myDoc->intSubset == NULL)
*************** xmlParseElementMixedContentDecl(xmlParse
*** 5216,5221 ****
--- 5248,5254 ----
}
NEXT;
ret = xmlNewDocElementContent(ctxt->myDoc, NULL,
XML_ELEMENT_CONTENT_PCDATA);
+ if (ret == NULL) return NULL;
if (RAW == '*') {
ret->ocur = XML_ELEMENT_CONTENT_MULT;
NEXT;
*************** xmlParseElementChildrenContentDecl (xmlP
*** 5471,5476 ****
--- 5504,5510 ----
return(NULL);
}
last = xmlNewDocElementContent(ctxt->myDoc, elem,
XML_ELEMENT_CONTENT_ELEMENT);
+ if (last == NULL) return NULL;
if (RAW == '?') {
last->ocur = XML_ELEMENT_CONTENT_OPT;
NEXT;
*************** xmlParseVersionNum(xmlParserCtxtPtr ctxt
*** 8980,8985 ****
--- 9014,9020 ----
size *= 2;
tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
if (tmp == NULL) {
+ xmlFree(buf);
xmlErrMemory(ctxt, NULL);
return(NULL);
}
_______________________________________________
xml mailing list, project page http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml