mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00
parser: Fix downstream code that swaps DTDs
Downstream code like the nginx xslt module can change the document's DTD pointers in a SAX callback. If an entity from a separate DTD is parsed lazily, its content must not reference the current document. Regressed with commit d025cfbb. Fixes #815.
This commit is contained in:
parent
0ec5687e06
commit
efb57ddba3
9
parser.c
9
parser.c
@ -12127,6 +12127,15 @@ xmlCtxtParseEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) {
|
||||
|
||||
while (list != NULL) {
|
||||
list->parent = (xmlNodePtr) ent;
|
||||
|
||||
/*
|
||||
* Downstream code like the nginx xslt module can set
|
||||
* ctxt->myDoc->extSubset to a separate DTD, so the entity
|
||||
* might have a different or a NULL document.
|
||||
*/
|
||||
if (list->doc != ent->doc)
|
||||
xmlSetTreeDoc(list, ent->doc);
|
||||
|
||||
if (list->next == NULL)
|
||||
ent->last = list;
|
||||
list = list->next;
|
||||
|
54
testparser.c
54
testparser.c
@ -128,6 +128,57 @@ testCFileIO(void) {
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef LIBXML_VALID_ENABLED
|
||||
static void
|
||||
testSwitchDtdExtSubset(void *vctxt, const xmlChar *name ATTRIBUTE_UNUSED,
|
||||
const xmlChar *externalId ATTRIBUTE_UNUSED,
|
||||
const xmlChar *systemId ATTRIBUTE_UNUSED) {
|
||||
xmlParserCtxtPtr ctxt = vctxt;
|
||||
|
||||
ctxt->myDoc->extSubset = ctxt->_private;
|
||||
}
|
||||
|
||||
static int
|
||||
testSwitchDtd(void) {
|
||||
const char dtdContent[] =
|
||||
"<!ENTITY test '<elem1/><elem2/>'>\n";
|
||||
const char docContent[] =
|
||||
"<!DOCTYPE doc SYSTEM 'entities.dtd'>\n"
|
||||
"<doc>&test;</doc>\n";
|
||||
xmlParserInputBufferPtr input;
|
||||
xmlParserCtxtPtr ctxt;
|
||||
xmlDtdPtr dtd;
|
||||
xmlDocPtr doc;
|
||||
xmlEntityPtr ent;
|
||||
int err = 0;
|
||||
|
||||
input = xmlParserInputBufferCreateStatic(dtdContent,
|
||||
sizeof(dtdContent) - 1,
|
||||
XML_CHAR_ENCODING_NONE);
|
||||
dtd = xmlIOParseDTD(NULL, input, XML_CHAR_ENCODING_NONE);
|
||||
|
||||
ctxt = xmlNewParserCtxt();
|
||||
ctxt->_private = dtd;
|
||||
ctxt->sax->externalSubset = testSwitchDtdExtSubset;
|
||||
doc = xmlCtxtReadMemory(ctxt, docContent, sizeof(docContent) - 1, NULL,
|
||||
NULL, XML_PARSE_NOENT | XML_PARSE_DTDLOAD);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
ent = xmlGetDocEntity(doc, BAD_CAST "test");
|
||||
if (ent->children->doc != NULL) {
|
||||
fprintf(stderr, "Entity content should have NULL doc\n");
|
||||
err = 1;
|
||||
}
|
||||
|
||||
/* Free doc before DTD */
|
||||
doc->extSubset = NULL;
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeDtd(dtd);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* LIBXML_VALID_ENABLED */
|
||||
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
static xmlChar *
|
||||
dumpNodeList(xmlNodePtr list) {
|
||||
@ -761,6 +812,9 @@ main(void) {
|
||||
err |= testUnsupportedEncoding();
|
||||
err |= testNodeGetContent();
|
||||
err |= testCFileIO();
|
||||
#ifdef LIBXML_VALID_ENABLED
|
||||
err |= testSwitchDtd();
|
||||
#endif
|
||||
#ifdef LIBXML_OUTPUT_ENABLED
|
||||
err |= testCtxtParseContent();
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user