mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-26 00:37:43 +03:00
fix for CVE-2008-3281 Daniel
* include/libxml/parser.h include/libxml/entities.h entities.c parserInternals.c parser.c: fix for CVE-2008-3281 Daniel svn path=/trunk/; revision=3772
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
Wed Aug 20 19:02:01 CEST 2008 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
|
* include/libxml/parser.h include/libxml/entities.h entities.c
|
||||||
|
parserInternals.c parser.c: fix for CVE-2008-3281
|
||||||
|
|
||||||
Sun Aug 10 17:06:13 CEST 2008 Rob Richards <rrichards@ctindustries.net>
|
Sun Aug 10 17:06:13 CEST 2008 Rob Richards <rrichards@ctindustries.net>
|
||||||
|
|
||||||
* dict.c: fix non GNUC builds.
|
* dict.c: fix non GNUC builds.
|
||||||
|
|||||||
10
entities.c
10
entities.c
@@ -31,35 +31,35 @@ static xmlEntity xmlEntityLt = {
|
|||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
BAD_CAST "<", BAD_CAST "<", 1,
|
BAD_CAST "<", BAD_CAST "<", 1,
|
||||||
XML_INTERNAL_PREDEFINED_ENTITY,
|
XML_INTERNAL_PREDEFINED_ENTITY,
|
||||||
NULL, NULL, NULL, NULL, 0, 1
|
NULL, NULL, NULL, NULL, 0, 1, 0
|
||||||
};
|
};
|
||||||
static xmlEntity xmlEntityGt = {
|
static xmlEntity xmlEntityGt = {
|
||||||
NULL, XML_ENTITY_DECL, BAD_CAST "gt",
|
NULL, XML_ENTITY_DECL, BAD_CAST "gt",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
BAD_CAST ">", BAD_CAST ">", 1,
|
BAD_CAST ">", BAD_CAST ">", 1,
|
||||||
XML_INTERNAL_PREDEFINED_ENTITY,
|
XML_INTERNAL_PREDEFINED_ENTITY,
|
||||||
NULL, NULL, NULL, NULL, 0, 1
|
NULL, NULL, NULL, NULL, 0, 1, 0
|
||||||
};
|
};
|
||||||
static xmlEntity xmlEntityAmp = {
|
static xmlEntity xmlEntityAmp = {
|
||||||
NULL, XML_ENTITY_DECL, BAD_CAST "amp",
|
NULL, XML_ENTITY_DECL, BAD_CAST "amp",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
BAD_CAST "&", BAD_CAST "&", 1,
|
BAD_CAST "&", BAD_CAST "&", 1,
|
||||||
XML_INTERNAL_PREDEFINED_ENTITY,
|
XML_INTERNAL_PREDEFINED_ENTITY,
|
||||||
NULL, NULL, NULL, NULL, 0, 1
|
NULL, NULL, NULL, NULL, 0, 1, 0
|
||||||
};
|
};
|
||||||
static xmlEntity xmlEntityQuot = {
|
static xmlEntity xmlEntityQuot = {
|
||||||
NULL, XML_ENTITY_DECL, BAD_CAST "quot",
|
NULL, XML_ENTITY_DECL, BAD_CAST "quot",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
BAD_CAST "\"", BAD_CAST "\"", 1,
|
BAD_CAST "\"", BAD_CAST "\"", 1,
|
||||||
XML_INTERNAL_PREDEFINED_ENTITY,
|
XML_INTERNAL_PREDEFINED_ENTITY,
|
||||||
NULL, NULL, NULL, NULL, 0, 1
|
NULL, NULL, NULL, NULL, 0, 1, 0
|
||||||
};
|
};
|
||||||
static xmlEntity xmlEntityApos = {
|
static xmlEntity xmlEntityApos = {
|
||||||
NULL, XML_ENTITY_DECL, BAD_CAST "apos",
|
NULL, XML_ENTITY_DECL, BAD_CAST "apos",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
BAD_CAST "'", BAD_CAST "'", 1,
|
BAD_CAST "'", BAD_CAST "'", 1,
|
||||||
XML_INTERNAL_PREDEFINED_ENTITY,
|
XML_INTERNAL_PREDEFINED_ENTITY,
|
||||||
NULL, NULL, NULL, NULL, 0, 1
|
NULL, NULL, NULL, NULL, 0, 1, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ struct _xmlEntity {
|
|||||||
const xmlChar *URI; /* the full URI as computed */
|
const xmlChar *URI; /* the full URI as computed */
|
||||||
int owner; /* does the entity own the childrens */
|
int owner; /* does the entity own the childrens */
|
||||||
int checked; /* was the entity content checked */
|
int checked; /* was the entity content checked */
|
||||||
|
unsigned long nbentities; /* the number of entities references */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -297,6 +297,7 @@ struct _xmlParserCtxt {
|
|||||||
*/
|
*/
|
||||||
xmlError lastError;
|
xmlError lastError;
|
||||||
xmlParserMode parseMode; /* the parser mode */
|
xmlParserMode parseMode; /* the parser mode */
|
||||||
|
unsigned long nbentities; /* number of entities references */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
37
parser.c
37
parser.c
@@ -2379,7 +2379,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
last = str + len;
|
last = str + len;
|
||||||
|
|
||||||
if (ctxt->depth > 40) {
|
if ((ctxt->depth > 40) || (ctxt->nbentities >= 500000)) {
|
||||||
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
@@ -2417,6 +2417,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
"String decoding Entity Reference: %.30s\n",
|
"String decoding Entity Reference: %.30s\n",
|
||||||
str);
|
str);
|
||||||
ent = xmlParseStringEntityRef(ctxt, &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 ((ent != NULL) &&
|
if ((ent != NULL) &&
|
||||||
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
if (ent->content != NULL) {
|
if (ent->content != NULL) {
|
||||||
@@ -2462,6 +2467,11 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"String decoding PE Reference: %.30s\n", str);
|
"String decoding PE Reference: %.30s\n", str);
|
||||||
ent = xmlParseStringPEReference(ctxt, &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 (ent != NULL) {
|
if (ent != NULL) {
|
||||||
if (ent->content == NULL) {
|
if (ent->content == NULL) {
|
||||||
if (xmlLoadEntityContent(ctxt, ent) < 0) {
|
if (xmlLoadEntityContent(ctxt, ent) < 0) {
|
||||||
@@ -2501,6 +2511,7 @@ xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
|
|||||||
|
|
||||||
mem_error:
|
mem_error:
|
||||||
xmlErrMemory(ctxt, NULL);
|
xmlErrMemory(ctxt, NULL);
|
||||||
|
int_error:
|
||||||
if (rep != NULL)
|
if (rep != NULL)
|
||||||
xmlFree(rep);
|
xmlFree(rep);
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
@@ -3542,6 +3553,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ent = xmlParseEntityRef(ctxt);
|
ent = xmlParseEntityRef(ctxt);
|
||||||
|
ctxt->nbentities++;
|
||||||
|
if (ent != NULL)
|
||||||
|
ctxt->nbentities += ent->nbentities;
|
||||||
if ((ent != NULL) &&
|
if ((ent != NULL) &&
|
||||||
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
if (len > buf_size - 10) {
|
if (len > buf_size - 10) {
|
||||||
@@ -4844,6 +4858,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
|
|||||||
int isParameter = 0;
|
int isParameter = 0;
|
||||||
xmlChar *orig = NULL;
|
xmlChar *orig = NULL;
|
||||||
int skipped;
|
int skipped;
|
||||||
|
unsigned long oldnbent = ctxt->nbentities;
|
||||||
|
|
||||||
/* GROW; done in the caller */
|
/* GROW; done in the caller */
|
||||||
if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
|
if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
|
||||||
@@ -5068,6 +5083,7 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cur != NULL) {
|
if (cur != NULL) {
|
||||||
|
cur->nbentities = ctxt->nbentities - oldnbent;
|
||||||
if (cur->orig != NULL)
|
if (cur->orig != NULL)
|
||||||
xmlFree(orig);
|
xmlFree(orig);
|
||||||
else
|
else
|
||||||
@@ -6477,6 +6493,11 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
if (ent == NULL) return;
|
if (ent == NULL) return;
|
||||||
if (!ctxt->wellFormed)
|
if (!ctxt->wellFormed)
|
||||||
return;
|
return;
|
||||||
|
ctxt->nbentities++;
|
||||||
|
if (ctxt->nbentities >= 500000) {
|
||||||
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
was_checked = ent->checked;
|
was_checked = ent->checked;
|
||||||
if ((ent->name != NULL) &&
|
if ((ent->name != NULL) &&
|
||||||
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
|
(ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
|
||||||
@@ -6537,6 +6558,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
xmlFreeNodeList(list);
|
xmlFreeNodeList(list);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
unsigned long oldnbent = ctxt->nbentities;
|
||||||
/*
|
/*
|
||||||
* 4.3.2: An internal general parsed entity is well-formed
|
* 4.3.2: An internal general parsed entity is well-formed
|
||||||
* if its replacement text matches the production labeled
|
* if its replacement text matches the production labeled
|
||||||
@@ -6559,6 +6581,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
ret = xmlParseBalancedChunkMemoryInternal(ctxt,
|
ret = xmlParseBalancedChunkMemoryInternal(ctxt,
|
||||||
value, user_data, &list);
|
value, user_data, &list);
|
||||||
ctxt->depth--;
|
ctxt->depth--;
|
||||||
|
|
||||||
} else if (ent->etype ==
|
} else if (ent->etype ==
|
||||||
XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
|
XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
|
||||||
ctxt->depth++;
|
ctxt->depth++;
|
||||||
@@ -6571,6 +6594,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
|
xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
|
||||||
"invalid entity type found\n", NULL);
|
"invalid entity type found\n", NULL);
|
||||||
}
|
}
|
||||||
|
ent->nbentities = ctxt->nbentities - oldnbent;
|
||||||
if (ret == XML_ERR_ENTITY_LOOP) {
|
if (ret == XML_ERR_ENTITY_LOOP) {
|
||||||
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
|
||||||
return;
|
return;
|
||||||
@@ -6629,6 +6653,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
|||||||
}
|
}
|
||||||
ent->checked = 1;
|
ent->checked = 1;
|
||||||
}
|
}
|
||||||
|
ctxt->nbentities += ent->nbentities;
|
||||||
|
|
||||||
if (ent->children == NULL) {
|
if (ent->children == NULL) {
|
||||||
/*
|
/*
|
||||||
@@ -11800,7 +11825,7 @@ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
|
|||||||
|
|
||||||
if (ctx == NULL) return(-1);
|
if (ctx == NULL) return(-1);
|
||||||
|
|
||||||
if (ctx->depth > 40) {
|
if ((ctx->depth > 40) || (ctx->nbentities >= 500000)) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12010,7 +12035,8 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|||||||
xmlChar start[4];
|
xmlChar start[4];
|
||||||
xmlCharEncoding enc;
|
xmlCharEncoding enc;
|
||||||
|
|
||||||
if (depth > 40) {
|
if ((depth > 40) ||
|
||||||
|
((oldctxt != NULL) && (oldctxt->nbentities >= 500000))) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12154,6 +12180,7 @@ xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
|
|||||||
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
|
oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
|
||||||
oldctxt->node_seq.length = ctxt->node_seq.length;
|
oldctxt->node_seq.length = ctxt->node_seq.length;
|
||||||
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
|
oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
|
||||||
|
oldctxt->nbentities += ctxt->nbentities;
|
||||||
ctxt->node_seq.maximum = 0;
|
ctxt->node_seq.maximum = 0;
|
||||||
ctxt->node_seq.length = 0;
|
ctxt->node_seq.length = 0;
|
||||||
ctxt->node_seq.buffer = NULL;
|
ctxt->node_seq.buffer = NULL;
|
||||||
@@ -12254,7 +12281,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
|
|||||||
int size;
|
int size;
|
||||||
xmlParserErrors ret = XML_ERR_OK;
|
xmlParserErrors ret = XML_ERR_OK;
|
||||||
|
|
||||||
if (oldctxt->depth > 40) {
|
if ((oldctxt->depth > 40) || (oldctxt->nbentities >= 500000)) {
|
||||||
return(XML_ERR_ENTITY_LOOP);
|
return(XML_ERR_ENTITY_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12379,6 +12406,7 @@ xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
|
|||||||
ctxt->myDoc->last = last;
|
ctxt->myDoc->last = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldctxt->nbentities += ctxt->nbentities;
|
||||||
ctxt->sax = oldsax;
|
ctxt->sax = oldsax;
|
||||||
ctxt->dict = NULL;
|
ctxt->dict = NULL;
|
||||||
ctxt->attsDefault = NULL;
|
ctxt->attsDefault = NULL;
|
||||||
@@ -13695,6 +13723,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->depth = 0;
|
ctxt->depth = 0;
|
||||||
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
||||||
ctxt->catalogs = NULL;
|
ctxt->catalogs = NULL;
|
||||||
|
ctxt->nbentities = 0;
|
||||||
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
||||||
|
|
||||||
if (ctxt->attsDefault != NULL) {
|
if (ctxt->attsDefault != NULL) {
|
||||||
|
|||||||
@@ -1670,6 +1670,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->depth = 0;
|
ctxt->depth = 0;
|
||||||
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
||||||
ctxt->catalogs = NULL;
|
ctxt->catalogs = NULL;
|
||||||
|
ctxt->nbentities = 0;
|
||||||
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
xmlInitNodeInfoSeq(&ctxt->node_seq);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user