1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-12-27 03:21:26 +03:00

parser: Fix DTD parser progress checks

This is another attempt at fixing parser progress checks. Instead of
relying on in->consumed, which could overflow, change some DTD parser
functions to make guaranteed progress on certain byte sequences.
This commit is contained in:
Nick Wellnhofer 2022-11-13 21:47:03 +01:00
parent 249cee4b2a
commit f61b8a6233
7 changed files with 78 additions and 68 deletions

116
parser.c
View File

@ -4900,7 +4900,8 @@ not_terminated:
*
* DEPRECATED: Internal function, don't use.
*
* Skip an XML (SGML) comment <!-- .... -->
* Parse an XML (SGML) comment. Always consumes '<!'.
*
* The spec says that "For compatibility, the string "--" (double-hyphen)
* must not occur within comments. "
*
@ -4923,12 +4924,15 @@ xmlParseComment(xmlParserCtxtPtr ctxt) {
/*
* Check that there is a comment right here.
*/
if ((RAW != '<') || (NXT(1) != '!') ||
(NXT(2) != '-') || (NXT(3) != '-')) return;
if ((RAW != '<') || (NXT(1) != '!'))
return;
SKIP(2);
if ((RAW != '-') || (NXT(1) != '-'))
return;
state = ctxt->instate;
ctxt->instate = XML_PARSER_COMMENT;
inputid = ctxt->input->id;
SKIP(4);
SKIP(2);
SHRINK;
GROW;
@ -5342,7 +5346,7 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
*
* DEPRECATED: Internal function, don't use.
*
* parse a notation declaration
* Parse a notation declaration. Always consumes '<!'.
*
* [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
*
@ -5360,10 +5364,14 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
xmlChar *Pubid;
xmlChar *Systemid;
if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
if ((CUR != '<') || (NXT(1) != '!'))
return;
SKIP(2);
if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
int inputid = ctxt->input->id;
SHRINK;
SKIP(10);
SKIP(8);
if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!NOTATION'\n");
@ -5416,7 +5424,7 @@ xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
*
* DEPRECATED: Internal function, don't use.
*
* parse <!ENTITY declarations
* Parse an entity declaration. Always consumes '<!'.
*
* [70] EntityDecl ::= GEDecl | PEDecl
*
@ -5443,11 +5451,15 @@ xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
int isParameter = 0;
xmlChar *orig = NULL;
if ((CUR != '<') || (NXT(1) != '!'))
return;
SKIP(2);
/* GROW; done in the caller */
if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
int inputid = ctxt->input->id;
SHRINK;
SKIP(8);
SKIP(6);
if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!ENTITY'\n");
@ -6006,7 +6018,7 @@ xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
*
* DEPRECATED: Internal function, don't use.
*
* : parse the Attribute list def for an element
* Parse an attribute list declaration for an element. Always consumes '<!'.
*
* [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
*
@ -6019,10 +6031,14 @@ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
const xmlChar *attrName;
xmlEnumerationPtr tree;
if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
if ((CUR != '<') || (NXT(1) != '!'))
return;
SKIP(2);
if (CMP7(CUR_PTR, 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
int inputid = ctxt->input->id;
SKIP(9);
SKIP(7);
if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after '<!ATTLIST'\n");
@ -6634,7 +6650,7 @@ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
*
* DEPRECATED: Internal function, don't use.
*
* parse an Element declaration.
* Parse an element declaration. Always consumes '<!'.
*
* [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
*
@ -6649,11 +6665,15 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
int ret = -1;
xmlElementContentPtr content = NULL;
if ((CUR != '<') || (NXT(1) != '!'))
return(ret);
SKIP(2);
/* GROW; done in the caller */
if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
if (CMP7(CUR_PTR, 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
int inputid = ctxt->input->id;
SKIP(9);
SKIP(7);
if (SKIP_BLANKS == 0) {
xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
"Space required after 'ELEMENT'\n");
@ -6741,6 +6761,8 @@ xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
* xmlParseConditionalSections
* @ctxt: an XML parser context
*
* Parse a conditional section. Always consumes '<!['.
*
* [61] conditionalSect ::= includeSect | ignoreSect
* [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
* [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
@ -6865,17 +6887,12 @@ xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
" in the same entity\n");
}
SKIP(3);
} else {
int id = ctxt->input->id;
unsigned long cons = CUR_CONSUMED;
} else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
xmlParseMarkupDecl(ctxt);
if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
xmlHaltParser(ctxt);
goto error;
}
} else {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
xmlHaltParser(ctxt);
goto error;
}
if (depth == 0)
@ -6895,7 +6912,7 @@ error:
*
* DEPRECATED: Internal function, don't use.
*
* parse Markup declarations
* Parse markup declarations. Always consumes '<!' or '<?'.
*
* [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
* NotationDecl | PI | Comment
@ -6924,6 +6941,8 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
xmlParseElementDecl(ctxt);
else if (NXT(3) == 'N')
xmlParseEntityDecl(ctxt);
else
SKIP(2);
break;
case 'A':
xmlParseAttributeListDecl(ctxt);
@ -6936,6 +6955,7 @@ xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
break;
default:
/* there is an error but it will be detected later */
SKIP(2);
break;
}
} else if (NXT(1) == '?') {
@ -7099,20 +7119,16 @@ xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
while (((RAW == '<') && (NXT(1) == '?')) ||
((RAW == '<') && (NXT(1) == '!')) ||
(RAW == '%')) {
int id = ctxt->input->id;
unsigned long cons = CUR_CONSUMED;
GROW;
if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
} else
xmlParseMarkupDecl(ctxt);
xmlParseConditionalSections(ctxt);
} else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
xmlParseMarkupDecl(ctxt);
} else {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
break;
}
SKIP_BLANKS;
if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
break;
}
}
if (RAW != 0) {
@ -7947,7 +7963,8 @@ xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
*
* DEPRECATED: Internal function, don't use.
*
* parse PEReference declarations
* Parse a parameter entity reference. Always consumes '%'.
*
* The entity content is handled directly by pushing it's content as
* a new input stream.
*
@ -8430,14 +8447,9 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
* PEReferences.
* Subsequence (markupdecl | PEReference | S)*
*/
SKIP_BLANKS;
while (((RAW != ']') || (ctxt->inputNr > baseInputNr)) &&
(ctxt->instate != XML_PARSER_EOF)) {
int id = ctxt->input->id;
unsigned long cons = CUR_CONSUMED;
SKIP_BLANKS;
xmlParseMarkupDecl(ctxt);
xmlParsePEReference(ctxt);
/*
* Conditional sections are allowed from external entities included
@ -8446,16 +8458,20 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
if ((ctxt->inputNr > 1) && (ctxt->input->filename != NULL) &&
(RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
xmlParseConditionalSections(ctxt);
}
if ((id == ctxt->input->id) && (cons == CUR_CONSUMED)) {
} else if ((RAW == '<') && ((NXT(1) == '!') || (NXT(1) == '?'))) {
xmlParseMarkupDecl(ctxt);
} else if (RAW == '%') {
xmlParsePEReference(ctxt);
} else {
xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
"xmlParseInternalSubset: error detected in Markup declaration\n");
"xmlParseInternalSubset: error detected in"
" Markup declaration\n");
if (ctxt->inputNr > baseInputNr)
xmlPopInput(ctxt);
else
break;
}
}
SKIP_BLANKS;
}
if (RAW == ']') {
NEXT;

View File

@ -8,13 +8,10 @@ A<lbbbbbbbbbbbbbbbbbbb_
./test/errors/754946.xml:4: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
<![
^
^
./test/errors/754946.xml:4: parser error : DOCTYPE improperly terminated
<![
^
./test/errors/754946.xml:4: parser error : StartTag: invalid element name
^
./test/errors/754946.xml:4: parser error : Start tag expected, '<' not found
<![
^
./test/errors/754946.xml:4: parser error : Extra content at the end of the document
<![
^
^

View File

@ -8,13 +8,10 @@ A<lbbbbbbbbbbbbbbbbbbb_
./test/errors/754946.xml:4: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
<![
^
^
./test/errors/754946.xml:4: parser error : DOCTYPE improperly terminated
<![
^
./test/errors/754946.xml:4: parser error : StartTag: invalid element name
^
./test/errors/754946.xml:4: parser error : Start tag expected, '<' not found
<![
^
./test/errors/754946.xml:4: parser error : Extra content at the end of the document
<![
^
^

View File

@ -22,7 +22,7 @@ Entity: line 1:
^
Entity: line 2:
<![INCLUDE[
^
^
./test/errors/759573-2.xml:6: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
%xx;ÿggKENSMYNT&#35;MENTD&#372zz;'>

View File

@ -22,7 +22,7 @@ Entity: line 1:
^
Entity: line 2:
<![INCLUDE[
^
^
./test/errors/759573-2.xml:6: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
%xx;ÿggKENSMYNT&#35;MENTD&#372zz;'>

View File

@ -19,7 +19,7 @@ T t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;000&#37;z;'><!ENTITYz>%xx;
^
Entity: line 1:
%<![INCLUDE[000%ஸ000%z;
^
^
./test/errors/759573.xml:1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
T t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;000&#37;z;'><!ENTITYz>%xx;

View File

@ -19,7 +19,7 @@ T t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;000&#37;z;'><!ENTITYz>%xx;
^
Entity: line 1:
%<![INCLUDE[000%ஸ000%z;
^
^
./test/errors/759573.xml:1: parser error : internal error: xmlParseInternalSubset: error detected in Markup declaration
T t (A)><!ENTITY % xx '&#37;<![INCLUDE[000&#37;&#3000;000&#37;z;'><!ENTITYz>%xx;