--- file_not_specified_in_diff +++ file_not_specified_in_diff @@ -, +, @@ --- libxml2-2.6.32.dfsg.orig/entities.c +++ libxml2-2.6.32.dfsg/entities.c @@ -102,7 +102,7 @@ dict = entity->doc->dict; - if ((entity->children) && (entity->owner == 1) && + if ((entity->children) && (entity->owner != 0) && (entity == (xmlEntityPtr) entity->children->parent)) xmlFreeNodeList(entity->children); if (dict != NULL) { --- libxml2-2.6.32.dfsg.orig/parser.c +++ libxml2-2.6.32.dfsg/parser.c @@ -2344,7 +2344,7 @@ return(NULL); last = str + len; - if (ctxt->depth > 40) { + if ((ctxt->depth > 40) || (ctxt->nbentities >= 500000)) { xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); return(NULL); } @@ -2382,6 +2382,11 @@ "String decoding Entity Reference: %.30s\n", str); ent = xmlParseStringEntityRef(ctxt, &str); + if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) + goto int_error; + ctxt->nbentities++; + if (ent != NULL) + ctxt->nbentities += ent->owner; if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (ent->content != NULL) { @@ -2427,6 +2432,11 @@ xmlGenericError(xmlGenericErrorContext, "String decoding PE Reference: %.30s\n", str); ent = xmlParseStringPEReference(ctxt, &str); + if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) + goto int_error; + ctxt->nbentities++; + if (ent != NULL) + ctxt->nbentities += ent->owner; if (ent != NULL) { if (ent->content == NULL) { if (xmlLoadEntityContent(ctxt, ent) < 0) { @@ -2468,6 +2478,7 @@ xmlErrMemory(ctxt, NULL); if (rep != NULL) xmlFree(rep); +int_error: if (buffer != NULL) xmlFree(buffer); return(NULL); @@ -3280,6 +3291,9 @@ } } else { ent = xmlParseEntityRef(ctxt); + ctxt->nbentities++; + if (ent != NULL) + ctxt->nbentities += ent->owner; if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (len > buf_size - 10) { @@ -4566,6 +4580,7 @@ int isParameter = 0; xmlChar *orig = NULL; int skipped; + unsigned long oldnbent = ctxt->nbentities; /* GROW; done in the caller */ if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) { @@ -4783,6 +4798,11 @@ } } if (cur != NULL) { + if ((cur->owner != 0) || (cur->children == NULL)) { + cur->owner = ctxt->nbentities - oldnbent; + if (cur->owner == 0) + cur->owner = 1; + } if (cur->orig != NULL) xmlFree(orig); else @@ -6189,6 +6209,11 @@ if (ent == NULL) return; if (!ctxt->wellFormed) return; + ctxt->nbentities++; + if (ctxt->nbentities >= 500000) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + return; + } was_checked = ent->checked; if ((ent->name != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) { @@ -6240,7 +6265,8 @@ (ent->children == NULL)) { ent->children = list; ent->last = list; - ent->owner = 1; + if (ent->owner == 0) + ent->owner = 1; list->parent = (xmlNodePtr) ent; } else { xmlFreeNodeList(list); @@ -6249,6 +6275,7 @@ xmlFreeNodeList(list); } } else { + unsigned long oldnbent = ctxt->nbentities; /* * 4.3.2: An internal general parsed entity is well-formed * if its replacement text matches the production labeled @@ -6271,6 +6298,7 @@ ret = xmlParseBalancedChunkMemoryInternal(ctxt, value, user_data, &list); ctxt->depth--; + } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { ctxt->depth++; @@ -6283,6 +6311,11 @@ xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, "invalid entity type found\n", NULL); } + if ((ent->owner != 0) || (ent->children == NULL)) { + ent->owner = ctxt->nbentities - oldnbent; + if (ent->owner == 0) + ent->owner = 1; + } if (ret == XML_ERR_ENTITY_LOOP) { xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); return; @@ -6301,7 +6334,8 @@ (ctxt->parseMode == XML_PARSE_READER)) { list->parent = (xmlNodePtr) ent; list = NULL; - ent->owner = 1; + if (ent->owner == 0) + ent->owner = 1; } else { ent->owner = 0; while (list != NULL) { @@ -6318,7 +6352,8 @@ #endif /* LIBXML_LEGACY_ENABLED */ } } else { - ent->owner = 1; + if (ent->owner == 0) + ent->owner = 1; while (list != NULL) { list->parent = (xmlNodePtr) ent; if (list->next == NULL) @@ -6393,6 +6428,7 @@ } return; } + ctxt->nbentities += ent->owner; if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { /* @@ -6495,7 +6531,8 @@ break; cur = next; } - ent->owner = 1; + if (ent->owner == 0) + ent->owner = 1; #ifdef LIBXML_LEGACY_ENABLED if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) xmlAddEntityReference(ent, firstChild, nw); @@ -11480,7 +11517,7 @@ if (ctx == NULL) return(-1); - if (ctx->depth > 40) { + if ((ctx->depth > 40) || (ctx->nbentities >= 500000)) { return(XML_ERR_ENTITY_LOOP); } @@ -11681,7 +11718,8 @@ xmlChar start[4]; xmlCharEncoding enc; - if (depth > 40) { + if ((depth > 40) || + ((oldctxt != NULL) && (oldctxt->nbentities >= 500000))) { return(XML_ERR_ENTITY_LOOP); } @@ -11824,6 +11862,7 @@ oldctxt->node_seq.maximum = ctxt->node_seq.maximum; oldctxt->node_seq.length = ctxt->node_seq.length; oldctxt->node_seq.buffer = ctxt->node_seq.buffer; + oldctxt->nbentities += ctxt->nbentities; ctxt->node_seq.maximum = 0; ctxt->node_seq.length = 0; ctxt->node_seq.buffer = NULL; @@ -11924,7 +11963,7 @@ int size; xmlParserErrors ret = XML_ERR_OK; - if (oldctxt->depth > 40) { + if ((oldctxt->depth > 40) || (oldctxt->nbentities >= 500000)) { return(XML_ERR_ENTITY_LOOP); } @@ -12048,6 +12087,7 @@ ctxt->myDoc->last = last; } + oldctxt->nbentities += ctxt->nbentities; ctxt->sax = oldsax; ctxt->dict = NULL; ctxt->attsDefault = NULL; @@ -13363,6 +13403,7 @@ ctxt->depth = 0; ctxt->charset = XML_CHAR_ENCODING_UTF8; ctxt->catalogs = NULL; + ctxt->nbentities = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); if (ctxt->attsDefault != NULL) { --- libxml2-2.6.32.dfsg.orig/include/libxml/parser.h +++ libxml2-2.6.32.dfsg/include/libxml/parser.h @@ -297,6 +297,7 @@ */ xmlError lastError; xmlParserMode parseMode; /* the parser mode */ + unsigned long nbentities; /* number of entities references */ }; /** --- libxml2-2.6.32.dfsg.orig/parserInternals.c +++ libxml2-2.6.32.dfsg/parserInternals.c @@ -1669,6 +1669,7 @@ ctxt->depth = 0; ctxt->charset = XML_CHAR_ENCODING_UTF8; ctxt->catalogs = NULL; + ctxt->nbentities = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); return(0); }