[3.12] gh-115398: Expose Expat >=2.6.0 reparse deferral API (CVE-2023-52425) (GH-115623) (GH-116248)

Allow controlling Expat >=2.6.0 reparse deferral (CVE-2023-52425) by adding five new methods:

- `xml.etree.ElementTree.XMLParser.flush`
- `xml.etree.ElementTree.XMLPullParser.flush`
- `xml.parsers.expat.xmlparser.GetReparseDeferralEnabled`
- `xml.parsers.expat.xmlparser.SetReparseDeferralEnabled`
- `xml.sax.expatreader.ExpatParser.flush`

Based on the "flush" idea from https://github.com/python/cpython/pull/115138#issuecomment-1932444270 .

- Please treat as a security fix related to CVE-2023-52425.

(cherry picked from commit 6a95676bb5)
(cherry picked from commit 73807eb634)
(cherry picked from commit eda2963378)

---------

Includes code suggested-by: Snild Dolkow <snild@sony.com>
and by core dev Serhiy Storchaka.
Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
Sebastian Pipping 2024-03-06 23:01:45 +01:00 committed by GitHub
parent 2528e46470
commit 0a01ed6c2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 439 additions and 21 deletions

View file

@ -3895,6 +3895,40 @@ _elementtree_XMLParser_close_impl(XMLParserObject *self)
}
}
/*[clinic input]
_elementtree.XMLParser.flush
[clinic start generated code]*/
static PyObject *
_elementtree_XMLParser_flush_impl(XMLParserObject *self)
/*[clinic end generated code: output=42fdb8795ca24509 input=effbecdb28715949]*/
{
if (!_check_xmlparser(self)) {
return NULL;
}
elementtreestate *st = self->state;
if (EXPAT(st, SetReparseDeferralEnabled) == NULL) {
Py_RETURN_NONE;
}
// NOTE: The Expat parser in the C implementation of ElementTree is not
// exposed to the outside; as a result we known that reparse deferral
// is currently enabled, or we would not even have access to function
// XML_SetReparseDeferralEnabled in the first place (which we checked
// for, a few lines up).
EXPAT(st, SetReparseDeferralEnabled)(self->parser, XML_FALSE);
PyObject *res = expat_parse(st, self, "", 0, XML_FALSE);
EXPAT(st, SetReparseDeferralEnabled)(self->parser, XML_TRUE);
return res;
}
/*[clinic input]
_elementtree.XMLParser.feed
@ -4289,6 +4323,7 @@ static PyType_Spec treebuilder_spec = {
static PyMethodDef xmlparser_methods[] = {
_ELEMENTTREE_XMLPARSER_FEED_METHODDEF
_ELEMENTTREE_XMLPARSER_CLOSE_METHODDEF
_ELEMENTTREE_XMLPARSER_FLUSH_METHODDEF
_ELEMENTTREE_XMLPARSER__PARSE_WHOLE_METHODDEF
_ELEMENTTREE_XMLPARSER__SETEVENTS_METHODDEF
{NULL, NULL}