summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog7
-rw-r--r--entities.c10
-rw-r--r--include/libxml/entities.h1
-rw-r--r--parser.c69
-rw-r--r--parserInternals.c1
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
diff --git a/entities.c b/entities.c
index 1abf8c8..91a3978 100644
--- a/entities.c
+++ b/entities.c
@@ -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 */
};
/*
diff --git a/parser.c b/parser.c
index 2f28c12..7e945b4 100644
--- a/parser.c
+++ b/parser.c
@@ -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);
}