diff options
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | entities.c | 10 | ||||
-rw-r--r-- | include/libxml/entities.h | 1 | ||||
-rw-r--r-- | parser.c | 69 | ||||
-rw-r--r-- | parserInternals.c | 1 |
5 files changed, 53 insertions, 35 deletions
diff --git a/debian/changelog b/debian/changelog index be0c773..a7f4944 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +libxml2 (2.6.27.dfsg-4) stable-security; urgency=low + + * Avoid growing the xmlEntity array while fixing CVE-2008-3281, so that + librsvg doesn't get broken. + + -- Mike Hommey <glandium@debian.org> Mon, 25 Aug 2008 20:08:47 +0200 + libxml2 (2.6.27.dfsg-3) stable-security; urgency=high * Non-maintainer upload by the security team @@ -31,35 +31,35 @@ static xmlEntity xmlEntityLt = { NULL, NULL, NULL, NULL, NULL, NULL, BAD_CAST "<", BAD_CAST "<", 1, XML_INTERNAL_PREDEFINED_ENTITY, - NULL, NULL, NULL, NULL, 0, 0 + NULL, NULL, NULL, NULL, 0, 1 }; static xmlEntity xmlEntityGt = { NULL, XML_ENTITY_DECL, BAD_CAST "gt", NULL, NULL, NULL, NULL, NULL, NULL, BAD_CAST ">", BAD_CAST ">", 1, XML_INTERNAL_PREDEFINED_ENTITY, - NULL, NULL, NULL, NULL, 0, 0 + NULL, NULL, NULL, NULL, 0, 1 }; static xmlEntity xmlEntityAmp = { NULL, XML_ENTITY_DECL, BAD_CAST "amp", NULL, NULL, NULL, NULL, NULL, NULL, BAD_CAST "&", BAD_CAST "&", 1, XML_INTERNAL_PREDEFINED_ENTITY, - NULL, NULL, NULL, NULL, 0, 0 + NULL, NULL, NULL, NULL, 0, 1 }; static xmlEntity xmlEntityQuot = { NULL, XML_ENTITY_DECL, BAD_CAST "quot", NULL, NULL, NULL, NULL, NULL, NULL, BAD_CAST "\"", BAD_CAST "\"", 1, XML_INTERNAL_PREDEFINED_ENTITY, - NULL, NULL, NULL, NULL, 0, 0 + NULL, NULL, NULL, NULL, 0, 1 }; static xmlEntity xmlEntityApos = { NULL, XML_ENTITY_DECL, BAD_CAST "apos", NULL, NULL, NULL, NULL, NULL, NULL, BAD_CAST "'", BAD_CAST "'", 1, XML_INTERNAL_PREDEFINED_ENTITY, - NULL, NULL, NULL, NULL, 0, 0 + NULL, NULL, NULL, NULL, 0, 1 }; /** diff --git a/include/libxml/entities.h b/include/libxml/entities.h index 838cd51..fdd7222 100644 --- a/include/libxml/entities.h +++ b/include/libxml/entities.h @@ -57,7 +57,6 @@ struct _xmlEntity { const xmlChar *URI; /* the full URI as computed */ int owner; /* does the entity own the childrens */ int checked; /* was the entity content checked */ - unsigned long nbentities; /* the number of entities references */ }; /* @@ -2218,11 +2218,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, "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->nbentities; + 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) { @@ -2269,11 +2269,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len, 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->nbentities; + if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) + goto int_error; + ctxt->nbentities++; + if (ent != NULL) + ctxt->nbentities += ent->owner; if (ent != NULL) { xmlChar *rep; @@ -3122,10 +3122,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { } } else { ent = xmlParseEntityRef(ctxt); - ctxt->nbentities++; - if (ent != NULL) - ctxt->nbentities += ent->nbentities; - + ctxt->nbentities++; + if (ent != NULL) + ctxt->nbentities += ent->owner; if ((ent != NULL) && (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { if (len > buf_size - 10) { @@ -4593,7 +4592,11 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) { } } if (cur != NULL) { - cur->nbentities = ctxt->nbentities - oldnbent; + 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 @@ -5972,12 +5975,11 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { if (ent == NULL) return; if (!ctxt->wellFormed) return; - ctxt->nbentities++; - if (ctxt->nbentities >= 500000) { - xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); - 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)) { @@ -6029,7 +6031,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { (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); @@ -6038,7 +6041,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { xmlFreeNodeList(list); } } else { - unsigned long oldnbent = ctxt->nbentities; + unsigned long oldnbent = ctxt->nbentities; /* * 4.3.2: An internal general parsed entity is well-formed * if its replacement text matches the production labeled @@ -6061,6 +6064,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { ret = xmlParseBalancedChunkMemoryInternal(ctxt, value, user_data, &list); ctxt->depth--; + } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { ctxt->depth++; @@ -6073,7 +6077,11 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, "invalid entity type found\n", NULL); } - ent->nbentities = ctxt->nbentities - oldnbent; + 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; @@ -6092,7 +6100,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { (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) { @@ -6109,7 +6118,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { #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) @@ -6173,7 +6183,6 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { return; } } - ctxt->nbentities += ent->nbentities; if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { /* @@ -6184,6 +6193,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { } return; } + ctxt->nbentities += ent->owner; if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { /* @@ -6286,7 +6296,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) { 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); @@ -11350,7 +11361,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt, xmlCharEncoding enc; if ((depth > 40) || - ((oldctxt != NULL) && (oldctxt->nbentities >= 500000))) { + ((oldctxt != NULL) && (oldctxt->nbentities >= 500000))) { return(XML_ERR_ENTITY_LOOP); } diff --git a/parserInternals.c b/parserInternals.c index 3560f50..5aeb37d 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -1669,6 +1669,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt) ctxt->depth = 0; ctxt->charset = XML_CHAR_ENCODING_UTF8; ctxt->catalogs = NULL; + ctxt->nbentities = 0; xmlInitNodeInfoSeq(&ctxt->node_seq); return(0); } |