diff --git a/include/libxml/parser.h b/include/libxml/parser.h index a848dccf..5fa5f6c9 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -745,6 +745,19 @@ struct _xmlSAXHandler { setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; + /* + * `startElement` and `endElement` are only used by the legacy SAX1 + * interface and should not be used in new software. If you really + * have to enable SAX1, the preferred way is set the `initialized` + * member to 1 instead of XML_SAX2_MAGIC. + * + * For backward compatibility, it's also possible to set the + * `startElementNs` and `endElementNs` handlers to NULL. + * + * You can also set the XML_PARSE_SAX1 parser option, but versions + * older than 2.12.0 will probably crash if this option is provided + * together with custom SAX callbacks. + */ startElementSAXFunc startElement; endElementSAXFunc endElement; referenceSAXFunc reference; @@ -758,8 +771,14 @@ struct _xmlSAXHandler { getParameterEntitySAXFunc getParameterEntity; cdataBlockSAXFunc cdataBlock; externalSubsetSAXFunc externalSubset; + /* + * `initialized` should always be set to XML_SAX2_MAGIC to enable the + * modern SAX2 interface. + */ unsigned int initialized; - /* The following fields are extensions available only on version 2 */ + /* + * The following members are only used by the SAX2 interface. + */ void *_private; startElementNsSAX2Func startElementNs; endElementNsSAX2Func endElementNs; diff --git a/parser.c b/parser.c index e291049a..6b0eb421 100644 --- a/parser.c +++ b/parser.c @@ -863,7 +863,14 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { if (ctxt == NULL) return; sax = ctxt->sax; #ifdef LIBXML_SAX1_ENABLED - if ((sax) && (sax->initialized == XML_SAX2_MAGIC)) + /* + * Only enable SAX2 if there SAX2 element handlers, except when there + * are no element handlers at all. + */ + if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && + ((sax->startElementNs != NULL) || + (sax->endElementNs != NULL) || + ((sax->startElement == NULL) && (sax->endElement == NULL)))) ctxt->sax2 = 1; #else ctxt->sax2 = 1; diff --git a/testrecurse.c b/testrecurse.c index d76d80ac..63b6bc4d 100644 --- a/testrecurse.c +++ b/testrecurse.c @@ -646,6 +646,8 @@ static void initSAX(xmlParserCtxtPtr ctxt) { ctxt->sax->startElementNs = NULL; ctxt->sax->endElementNs = NULL; + ctxt->sax->startElement = NULL; + ctxt->sax->endElement = NULL; ctxt->sax->characters = NULL; ctxt->sax->cdataBlock = NULL; ctxt->sax->ignorableWhitespace = NULL;