aboutsummaryrefslogtreecommitdiff
path: root/textproc/libxml2
diff options
context:
space:
mode:
authorJeremy Messenger <mezz@FreeBSD.org>2008-10-20 16:11:29 +0000
committerJeremy Messenger <mezz@FreeBSD.org>2008-10-20 16:11:29 +0000
commit462449fa0682abf40b1446f0067d5e07806702fd (patch)
treeda700f0c31fd743d31e6de40153a37efc895471d /textproc/libxml2
parentb99ff506e43494109cefe260394f28565849dd0f (diff)
Notes
Diffstat (limited to 'textproc/libxml2')
-rw-r--r--textproc/libxml2/Makefile2
-rw-r--r--textproc/libxml2/files/patch-CVE-2008-3281412
-rw-r--r--textproc/libxml2/files/patch-CVE-2008-352919
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--)