diff options
author | Jeremy Messenger <mezz@FreeBSD.org> | 2008-10-20 16:11:29 +0000 |
---|---|---|
committer | Jeremy Messenger <mezz@FreeBSD.org> | 2008-10-20 16:11:29 +0000 |
commit | 462449fa0682abf40b1446f0067d5e07806702fd (patch) | |
tree | da700f0c31fd743d31e6de40153a37efc895471d /textproc/libxml2 | |
parent | b99ff506e43494109cefe260394f28565849dd0f (diff) |
Notes
Diffstat (limited to 'textproc/libxml2')
-rw-r--r-- | textproc/libxml2/Makefile | 2 | ||||
-rw-r--r-- | textproc/libxml2/files/patch-CVE-2008-3281 | 412 | ||||
-rw-r--r-- | textproc/libxml2/files/patch-CVE-2008-3529 | 19 |
3 files changed, 432 insertions, 1 deletions
diff --git a/textproc/libxml2/Makefile b/textproc/libxml2/Makefile index ebc79b06b0c9..a936555b8471 100644 --- a/textproc/libxml2/Makefile +++ b/textproc/libxml2/Makefile @@ -13,7 +13,7 @@ PORTNAME= libxml2 PORTVERSION= 2.6.32 -PORTREVISION?= 0 +PORTREVISION?= 1 CATEGORIES?= textproc gnome MASTER_SITES= ftp://fr.rpmfind.net/pub/libxml/ \ ftp://gd.tuwien.ac.at/pub/libxml/ \ diff --git a/textproc/libxml2/files/patch-CVE-2008-3281 b/textproc/libxml2/files/patch-CVE-2008-3281 new file mode 100644 index 000000000000..b8fa9047e4bb --- /dev/null +++ b/textproc/libxml2/files/patch-CVE-2008-3281 @@ -0,0 +1,412 @@ +diff -pruN libxml2-2.6.31.cve-2008-3281/entities.c libxml2-2.6.31/entities.c +--- libxml2-2.6.31.cve-2008-3281/entities.c 2007-01-03 08:07:52.000000000 -0500 ++++ entities.c 2008-09-11 16:08:42.000000000 -0400 +@@ -102,7 +102,7 @@ xmlFreeEntity(xmlEntityPtr entity) + 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) { +diff -pruN libxml2-2.6.31.cve-2008-3281/include/libxml/parser.h libxml2-2.6.31/include/libxml/parser.h +--- libxml2-2.6.31.cve-2008-3281/include/libxml/parser.h 2007-01-03 08:07:30.000000000 -0500 ++++ include/libxml/parser.h 2008-09-11 16:08:42.000000000 -0400 +@@ -297,6 +297,8 @@ struct _xmlParserCtxt { + */ + xmlError lastError; + xmlParserMode parseMode; /* the parser mode */ ++ unsigned long nbentities; /* number of entities references */ ++ unsigned long sizeentities; /* size of parsed entities */ + }; + + /** +diff -pruN libxml2-2.6.31.cve-2008-3281/parser.c libxml2-2.6.31/parser.c +--- libxml2-2.6.31.cve-2008-3281/parser.c 2008-01-11 01:36:20.000000000 -0500 ++++ parser.c 2008-09-11 16:10:45.000000000 -0400 +@@ -80,6 +80,95 @@ + #include <zlib.h> + #endif + ++static void ++xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info); ++ ++/************************************************************************ ++ * * ++ * Arbitrary limits set in the parser. * ++ * * ++ ************************************************************************/ ++ ++#define XML_PARSER_BIG_ENTITY 1000 ++#define XML_PARSER_LOT_ENTITY 5000 ++ ++/* ++ * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity ++ * replacement over the size in byte of the input indicates that you have ++ * and eponential behaviour. A value of 10 correspond to at least 3 entity ++ * replacement per byte of input. ++ */ ++#define XML_PARSER_NON_LINEAR 10 ++ ++/* ++ * xmlParserEntityCheck ++ * ++ * Function to check non-linear entity expansion behaviour ++ * This is here to detect and stop exponential linear entity expansion ++ * This is not a limitation of the parser but a safety ++ * boundary feature. ++ */ ++static int ++xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size, ++ xmlEntityPtr ent) ++{ ++ unsigned long consumed = 0; ++ ++ if (ctxt == NULL) ++ return (0); ++ if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ++ return (1); ++ if (size != 0) { ++ /* ++ * Do the check based on the replacement size of the entity ++ */ ++ if (size < XML_PARSER_BIG_ENTITY) ++ return(0); ++ ++ /* ++ * A limit on the amount of text data reasonably used ++ */ ++ if (ctxt->input != NULL) { ++ consumed = ctxt->input->consumed + ++ (ctxt->input->cur - ctxt->input->base); ++ } ++ consumed += ctxt->sizeentities; ++ ++ if ((size < XML_PARSER_NON_LINEAR * consumed) && ++ (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed)) ++ return (0); ++ } else if (ent != NULL) { ++ /* ++ * use the number of parsed entities in the replacement ++ */ ++ size = ent->owner; ++ ++ /* ++ * The amount of data parsed counting entities size only once ++ */ ++ if (ctxt->input != NULL) { ++ consumed = ctxt->input->consumed + ++ (ctxt->input->cur - ctxt->input->base); ++ } ++ consumed += ctxt->sizeentities; ++ ++ /* ++ * Check the density of entities for the amount of data ++ * knowing an entity reference will take at least 3 bytes ++ */ ++ if (size * 3 < consumed * XML_PARSER_NON_LINEAR) ++ return (0); ++ } else { ++ /* ++ * strange we got no data for checking just return ++ */ ++ return (0); ++ } ++ ++ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); ++ return (1); ++} ++ + /** + * xmlParserMaxDepth: + * +@@ -2260,6 +2349,10 @@ xmlStringLenDecodeEntities(xmlParserCtxt + "String decoding Entity Reference: %.30s\n", + str); + ent = xmlParseStringEntityRef(ctxt, &str); ++ if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ++ goto int_error; ++ if (ent != NULL) ++ ctxt->nbentities += ent->owner; + if ((ent != NULL) && + (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { + if (ent->content != NULL) { +@@ -2284,6 +2377,10 @@ xmlStringLenDecodeEntities(xmlParserCtxt + buffer[nbchars++] = *current++; + if (nbchars > + buffer_size - XML_PARSER_BUFFER_SIZE) { ++ if (xmlParserEntityCheck(ctxt, nbchars, ent)) { ++ xmlFree(rep); ++ goto int_error; ++ } + growBuffer(buffer); + } + } +@@ -2306,6 +2403,10 @@ xmlStringLenDecodeEntities(xmlParserCtxt + xmlGenericError(xmlGenericErrorContext, + "String decoding PE Reference: %.30s\n", str); + ent = xmlParseStringPEReference(ctxt, &str); ++ if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ++ goto int_error; ++ if (ent != NULL) ++ ctxt->nbentities += ent->owner; + if (ent != NULL) { + xmlChar *rep; + +@@ -2319,6 +2420,10 @@ xmlStringLenDecodeEntities(xmlParserCtxt + buffer[nbchars++] = *current++; + if (nbchars > + buffer_size - XML_PARSER_BUFFER_SIZE) { ++ if (xmlParserEntityCheck(ctxt, nbchars, ent)) { ++ xmlFree(rep); ++ goto int_error; ++ } + growBuffer(buffer); + } + } +@@ -2466,6 +2571,7 @@ xmlStringLenDecodeEntities(xmlParserCtxt + + mem_error: + xmlErrMemory(ctxt, NULL); ++int_error: + if (rep != NULL) + xmlFree(rep); + if (buffer != NULL) +@@ -3151,6 +3259,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr + } + } 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) { +@@ -4433,6 +4544,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt + 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')) { +@@ -4642,6 +4754,11 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt + } + } + 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 +@@ -6071,7 +6188,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); +@@ -6080,6 +6198,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) + 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 +@@ -6102,6 +6221,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) + ret = xmlParseBalancedChunkMemoryInternal(ctxt, + value, user_data, &list); + ctxt->depth--; ++ + } else if (ent->etype == + XML_EXTERNAL_GENERAL_PARSED_ENTITY) { + ctxt->depth++; +@@ -6114,6 +6234,24 @@ xmlParseReference(xmlParserCtxtPtr ctxt) + xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, + "invalid entity type found\n", NULL); + } ++ /* ++ * Store the number of entities needing parsing for entity ++ * content and do checkings ++ */ ++ 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); ++ xmlFreeNodeList(list); ++ return; ++ } ++ if (xmlParserEntityCheck(ctxt, 0, ent)) { ++ xmlFreeNodeList(list); ++ return; ++ } + if (ret == XML_ERR_ENTITY_LOOP) { + xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); + return; +@@ -6132,7 +6270,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) { +@@ -6149,7 +6288,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) +@@ -6326,7 +6466,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); +@@ -6357,6 +6498,8 @@ xmlParseReference(xmlParserCtxtPtr ctxt) + ctxt->nodelen = 0; + return; + } ++ } else if (ent->owner != 1) { ++ ctxt->nbentities += ent->owner; + } + } else { + val = ent->content; +@@ -6416,6 +6559,11 @@ xmlParseEntityRef(xmlParserCtxtPtr ctxt) + if (RAW == ';') { + NEXT; + /* ++ * Increase the number of entity references parsed ++ */ ++ ctxt->nbentities++; ++ ++ /* + * Ask first SAX for entity resolution, otherwise try the + * predefined set. + */ +@@ -6587,6 +6735,10 @@ xmlParseStringEntityRef(xmlParserCtxtPtr + if (*ptr == ';') { + ptr++; + /* ++ * Increase the number of entity references parsed ++ */ ++ ctxt->nbentities++; ++ /* + * Ask first SAX for entity resolution, otherwise try the + * predefined set. + */ +@@ -6748,6 +6900,11 @@ xmlParsePEReference(xmlParserCtxtPtr ctx + } else { + if (RAW == ';') { + NEXT; ++ /* ++ * Increase the number of entity references parsed ++ */ ++ ctxt->nbentities++; ++ + if ((ctxt->sax != NULL) && + (ctxt->sax->getParameterEntity != NULL)) + entity = ctxt->sax->getParameterEntity(ctxt->userData, +@@ -6878,6 +7035,11 @@ xmlParseStringPEReference(xmlParserCtxtP + if (cur == ';') { + ptr++; + cur = *ptr; ++ /* ++ * Increase the number of entity references parsed ++ */ ++ ctxt->nbentities++; ++ + if ((ctxt->sax != NULL) && + (ctxt->sax->getParameterEntity != NULL)) + entity = ctxt->sax->getParameterEntity(ctxt->userData, +@@ -11537,11 +11699,31 @@ xmlParseExternalEntityPrivate(xmlDocPtr + } + ret = XML_ERR_OK; + } ++ ++ /* ++ * Record in the parent context the number of entities replacement ++ * done when parsing that reference. ++ */ ++ oldctxt->nbentities += ctxt->nbentities; ++ /* ++ * Also record the size of the entity parsed ++ */ ++ if (ctxt->input != NULL) { ++ oldctxt->sizeentities += ctxt->input->consumed; ++ oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base); ++ } ++ /* ++ * And record the last error if any ++ */ ++ if (ctxt->lastError.code != XML_ERR_OK) ++ xmlCopyError(&ctxt->lastError, &oldctxt->lastError); ++ + if (sax != NULL) + ctxt->sax = oldsax; + 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; +@@ -11766,6 +11948,17 @@ xmlParseBalancedChunkMemoryInternal(xmlP + ctxt->myDoc->last = last; + } + ++ /* ++ * Record in the parent context the number of entities replacement ++ * done when parsing that reference. ++ */ ++ oldctxt->nbentities += ctxt->nbentities; ++ /* ++ * Also record the last error if any ++ */ ++ if (ctxt->lastError.code != XML_ERR_OK) ++ xmlCopyError(&ctxt->lastError, &oldctxt->lastError); ++ + ctxt->sax = oldsax; + ctxt->dict = NULL; + ctxt->attsDefault = NULL; +@@ -13077,6 +13270,8 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt) + ctxt->depth = 0; + ctxt->charset = XML_CHAR_ENCODING_UTF8; + ctxt->catalogs = NULL; ++ ctxt->nbentities = 0; ++ ctxt->sizeentities = 0; + xmlInitNodeInfoSeq(&ctxt->node_seq); + + if (ctxt->attsDefault != NULL) { +diff -pruN libxml2-2.6.31.cve-2008-3281/parserInternals.c libxml2-2.6.31/parserInternals.c +--- libxml2-2.6.31.cve-2008-3281/parserInternals.c 2007-12-14 06:17:14.000000000 -0500 ++++ parserInternals.c 2008-09-11 16:08:42.000000000 -0400 +@@ -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); + } diff --git a/textproc/libxml2/files/patch-CVE-2008-3529 b/textproc/libxml2/files/patch-CVE-2008-3529 new file mode 100644 index 000000000000..943fa2b8005b --- /dev/null +++ b/textproc/libxml2/files/patch-CVE-2008-3529 @@ -0,0 +1,19 @@ +--- parser.c.orig 2008-09-03 15:55:59.000000000 +0200 ++++ parser.c 2008-09-03 16:30:22.000000000 +0200 +@@ -2301,6 +2301,7 @@ xmlParserHandlePEReference(xmlParserCtxt + */ + #define growBuffer(buffer) { \ + xmlChar *tmp; \ ++ buffer##_size += XML_PARSER_BUFFER_SIZE ; \ + buffer##_size *= 2; \ + tmp = (xmlChar *) \ + xmlRealloc(buffer, buffer##_size * sizeof(xmlChar)); \ +@@ -3341,7 +3342,7 @@ xmlParseAttValueComplex(xmlParserCtxtPtr + * Just output the reference + */ + buf[len++] = '&'; +- if (len > buf_size - i - 10) { ++ while (len > buf_size - i - 10) { + growBuffer(buf); + } + for (;i > 0;i--) |