OLD | NEW |
1 /* | 1 /* |
2 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly | 2 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly |
3 * implemented on top of the SAX interfaces | 3 * implemented on top of the SAX interfaces |
4 * | 4 * |
5 * References: | 5 * References: |
6 * The XML specification: | 6 * The XML specification: |
7 * http://www.w3.org/TR/REC-xml | 7 * http://www.w3.org/TR/REC-xml |
8 * Original 1.0 version: | 8 * Original 1.0 version: |
9 * http://www.w3.org/TR/1998/REC-xml-19980210 | 9 * http://www.w3.org/TR/1998/REC-xml-19980210 |
10 * XML second edition working draft | 10 * XML second edition working draft |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 | 130 |
131 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) | 131 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) |
132 return (0); | 132 return (0); |
133 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) | 133 if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP) |
134 return (1); | 134 return (1); |
135 | 135 |
136 /* | 136 /* |
137 * This may look absurd but is needed to detect | 137 * This may look absurd but is needed to detect |
138 * entities problems | 138 * entities problems |
139 */ | 139 */ |
| 140 if ((ent != NULL) && (ent->guard == XML_ENTITY_BEING_CHECKED)) { |
| 141 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); |
| 142 return (1); |
| 143 } |
140 if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && | 144 if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) && |
141 (ent->content != NULL) && (ent->checked == 0) && | 145 (ent->content != NULL) && (ent->checked == 0) && |
142 (ctxt->errNo != XML_ERR_ENTITY_LOOP)) { | 146 (ctxt->errNo != XML_ERR_ENTITY_LOOP)) { |
143 unsigned long oldnbent = ctxt->nbentities; | 147 unsigned long oldnbent = ctxt->nbentities; |
144 xmlChar *rep; | 148 xmlChar *rep; |
145 | 149 |
| 150 ent->guard = XML_ENTITY_BEING_CHECKED; |
146 ent->checked = 1; | 151 ent->checked = 1; |
147 | 152 |
148 ++ctxt->depth; | 153 ++ctxt->depth; |
149 rep = xmlStringDecodeEntities(ctxt, ent->content, | 154 rep = xmlStringDecodeEntities(ctxt, ent->content, |
150 XML_SUBSTITUTE_REF, 0, 0, 0); | 155 XML_SUBSTITUTE_REF, 0, 0, 0); |
151 --ctxt->depth; | 156 --ctxt->depth; |
| 157 ent->guard = XML_ENTITY_NOT_BEING_CHECKED; |
152 if (ctxt->errNo == XML_ERR_ENTITY_LOOP) { | 158 if (ctxt->errNo == XML_ERR_ENTITY_LOOP) { |
153 ent->content[0] = 0; | 159 ent->content[0] = 0; |
154 } | 160 } |
155 | 161 |
156 ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; | 162 ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; |
157 if (rep != NULL) { | 163 if (rep != NULL) { |
158 if (xmlStrchr(rep, '<')) | 164 if (xmlStrchr(rep, '<')) |
159 ent->checked |= 1; | 165 ent->checked |= 1; |
160 xmlFree(rep); | 166 xmlFree(rep); |
161 rep = NULL; | 167 rep = NULL; |
(...skipping 7160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7322 user_data = NULL; | 7328 user_data = NULL; |
7323 else | 7329 else |
7324 user_data = ctxt->userData; | 7330 user_data = ctxt->userData; |
7325 | 7331 |
7326 /* | 7332 /* |
7327 * Check that this entity is well formed | 7333 * Check that this entity is well formed |
7328 * 4.3.2: An internal general parsed entity is well-formed | 7334 * 4.3.2: An internal general parsed entity is well-formed |
7329 * if its replacement text matches the production labeled | 7335 * if its replacement text matches the production labeled |
7330 * content. | 7336 * content. |
7331 */ | 7337 */ |
7332 » if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { | 7338 if (ent->guard == XML_ENTITY_BEING_CHECKED) { |
7333 » ctxt->depth++; | 7339 ret = XML_ERR_ENTITY_LOOP; |
7334 » ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content, | 7340 } else { |
7335 » user_data, &list); | 7341 ent->guard = XML_ENTITY_BEING_CHECKED; |
7336 » ctxt->depth--; | 7342 if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { |
7337 | 7343 ctxt->depth++; |
7338 » } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { | 7344 ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content, |
7339 » ctxt->depth++; | 7345 user_data, &list); |
7340 » ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax, | 7346 ctxt->depth--; |
7341 » user_data, ctxt->depth, ent->URI, | 7347 } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) { |
7342 » » » » » ent->ExternalID, &list); | 7348 ctxt->depth++; |
7343 » ctxt->depth--; | 7349 ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax
, |
7344 » } else { | 7350 user_data, ctxt->depth, ent->URI, |
7345 » ret = XML_ERR_ENTITY_PE_INTERNAL; | 7351 ent->ExternalID, &list); |
7346 » xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, | 7352 ctxt->depth--; |
7347 » » » "invalid entity type found\n", NULL); | 7353 } else { |
7348 » } | 7354 ret = XML_ERR_ENTITY_PE_INTERNAL; |
| 7355 xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, |
| 7356 "invalid entity type found\n", NULL); |
| 7357 } |
| 7358 ent->guard = XML_ENTITY_NOT_BEING_CHECKED; |
| 7359 } |
7349 | 7360 |
7350 /* | 7361 /* |
7351 * Store the number of entities needing parsing for this entity | 7362 * Store the number of entities needing parsing for this entity |
7352 * content and do checkings | 7363 * content and do checkings |
7353 */ | 7364 */ |
7354 ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; | 7365 ent->checked = (ctxt->nbentities - oldnbent + 1) * 2; |
7355 if ((ent->content != NULL) && (xmlStrchr(ent->content, '<'))) | 7366 if ((ent->content != NULL) && (xmlStrchr(ent->content, '<'))) |
7356 ent->checked |= 1; | 7367 ent->checked |= 1; |
7357 if (ret == XML_ERR_ENTITY_LOOP) { | 7368 if (ret == XML_ERR_ENTITY_LOOP) { |
7358 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); | 7369 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7441 /* | 7452 /* |
7442 * This is a bit hackish but this seems the best | 7453 * This is a bit hackish but this seems the best |
7443 * way to make sure both SAX and DOM entity support | 7454 * way to make sure both SAX and DOM entity support |
7444 * behaves okay. | 7455 * behaves okay. |
7445 */ | 7456 */ |
7446 if (ctxt->userData == ctxt) | 7457 if (ctxt->userData == ctxt) |
7447 user_data = NULL; | 7458 user_data = NULL; |
7448 else | 7459 else |
7449 user_data = ctxt->userData; | 7460 user_data = ctxt->userData; |
7450 | 7461 |
7451 » if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { | 7462 if (ent->guard == XML_ENTITY_BEING_CHECKED) { |
7452 » » ctxt->depth++; | 7463 ret = XML_ERR_ENTITY_LOOP; |
7453 » » ret = xmlParseBalancedChunkMemoryInternal(ctxt, | 7464 } else { |
7454 » » » » ent->content, user_data, NULL); | 7465 ent->guard = XML_ENTITY_BEING_CHECKED; |
7455 » » ctxt->depth--; | 7466 if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) { |
7456 » } else if (ent->etype == | 7467 ctxt->depth++; |
7457 » » XML_EXTERNAL_GENERAL_PARSED_ENTITY) { | 7468 ret = xmlParseBalancedChunkMemoryInternal(ctxt, |
7458 » » ctxt->depth++; | 7469 ent->content, user_data, NULL); |
7459 » » ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, | 7470 ctxt->depth--; |
7460 » » » ctxt->sax, user_data, ctxt->depth, | 7471 } else if (ent->etype == |
7461 » » » ent->URI, ent->ExternalID, NULL); | 7472 XML_EXTERNAL_GENERAL_PARSED_ENTITY) { |
7462 » » ctxt->depth--; | 7473 ctxt->depth++; |
7463 » } else { | 7474 ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, |
7464 » » ret = XML_ERR_ENTITY_PE_INTERNAL; | 7475 ctxt->sax, user_data, ctxt->depth, |
7465 » » xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, | 7476 ent->URI, ent->ExternalID, NULL); |
7466 » » » "invalid entity type found\n", NULL); | 7477 ctxt->depth--; |
7467 » } | 7478 } else { |
| 7479 ret = XML_ERR_ENTITY_PE_INTERNAL; |
| 7480 xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR, |
| 7481 "invalid entity type found\n", NULL); |
| 7482 } |
| 7483 ent->guard = XML_ENTITY_NOT_BEING_CHECKED; |
| 7484 } |
7468 if (ret == XML_ERR_ENTITY_LOOP) { | 7485 if (ret == XML_ERR_ENTITY_LOOP) { |
7469 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); | 7486 xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); |
7470 return; | 7487 return; |
7471 } | 7488 } |
7472 } | 7489 } |
7473 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && | 7490 if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) && |
7474 (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { | 7491 (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) { |
7475 /* | 7492 /* |
7476 * Entity reference callback comes second, it's somewhat | 7493 * Entity reference callback comes second, it's somewhat |
7477 * superfluous but a compatibility to historical behaviour | 7494 * superfluous but a compatibility to historical behaviour |
(...skipping 8330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15808 if (stream == NULL) { | 15825 if (stream == NULL) { |
15809 xmlFreeParserInputBuffer(input); | 15826 xmlFreeParserInputBuffer(input); |
15810 return (NULL); | 15827 return (NULL); |
15811 } | 15828 } |
15812 inputPush(ctxt, stream); | 15829 inputPush(ctxt, stream); |
15813 return (xmlDoRead(ctxt, URL, encoding, options, 1)); | 15830 return (xmlDoRead(ctxt, URL, encoding, options, 1)); |
15814 } | 15831 } |
15815 | 15832 |
15816 #define bottom_parser | 15833 #define bottom_parser |
15817 #include "elfgcchack.h" | 15834 #include "elfgcchack.h" |
OLD | NEW |