gh-115398: Expose Expat >=2.6.0 reparse deferral API (CVE-2023-52425)… · hartwork/cpython@6a95676 (original) (raw)

`@@ -121,10 +121,6 @@

`

121

121

`

`

122

122

`"""

`

123

123

``

124

``

`-

fails_with_expat_2_6_0 = (unittest.expectedFailure

`

125

``

`-

if pyexpat.version_info >= (2, 6, 0) else

`

126

``

`-

lambda test: test)

`

127

``

-

128

124

`def checkwarnings(*filters, quiet=False):

`

129

125

`def decorator(test):

`

130

126

`def newtest(*args, **kwargs):

`

`@@ -1462,12 +1458,14 @@ def test_attlist_default(self):

`

1462

1458

``

1463

1459

`class XMLPullParserTest(unittest.TestCase):

`

1464

1460

``

1465

``

`-

def _feed(self, parser, data, chunk_size=None):

`

``

1461

`+

def _feed(self, parser, data, chunk_size=None, flush=False):

`

1466

1462

`if chunk_size is None:

`

1467

1463

`parser.feed(data)

`

1468

1464

`else:

`

1469

1465

`for i in range(0, len(data), chunk_size):

`

1470

1466

`parser.feed(data[i:i+chunk_size])

`

``

1467

`+

if flush:

`

``

1468

`+

parser.flush()

`

1471

1469

``

1472

1470

`def assert_events(self, parser, expected, max_events=None):

`

1473

1471

`self.assertEqual(

`

`@@ -1485,34 +1483,32 @@ def assert_event_tags(self, parser, expected, max_events=None):

`

1485

1483

`self.assertEqual([(action, elem.tag) for action, elem in events],

`

1486

1484

`expected)

`

1487

1485

``

1488

``

`-

def test_simple_xml(self, chunk_size=None):

`

``

1486

`+

def test_simple_xml(self, chunk_size=None, flush=False):

`

1489

1487

`parser = ET.XMLPullParser()

`

1490

1488

`self.assert_event_tags(parser, [])

`

1491

``

`-

self._feed(parser, "\n", chunk_size)

`

``

1489

`+

self._feed(parser, "\n", chunk_size, flush)

`

1492

1490

`self.assert_event_tags(parser, [])

`

1493

1491

`self._feed(parser,

`

1494

1492

`"\n text</element",

`

1495

``

`-

chunk_size)

`

``

1493

`+

chunk_size, flush)

`

1496

1494

`self.assert_event_tags(parser, [])

`

1497

``

`-

self._feed(parser, ">\n", chunk_size)

`

``

1495

`+

self._feed(parser, ">\n", chunk_size, flush)

`

1498

1496

`self.assert_event_tags(parser, [('end', 'element')])

`

1499

``

`-

self._feed(parser, "texttail\n", chunk_size)

`

1500

``

`-

self._feed(parser, "\n", chunk_size)

`

``

1497

`+

self._feed(parser, "texttail\n", chunk_size, flush)

`

``

1498

`+

self._feed(parser, "\n", chunk_size, flush)

`

1501

1499

`self.assert_event_tags(parser, [

`

1502

1500

` ('end', 'element'),

`

1503

1501

` ('end', 'empty-element'),

`

1504

1502

` ])

`

1505

``

`-

self._feed(parser, "\n", chunk_size)

`

``

1503

`+

self._feed(parser, "\n", chunk_size, flush)

`

1506

1504

`self.assert_event_tags(parser, [('end', 'root')])

`

1507

1505

`self.assertIsNone(parser.close())

`

1508

1506

``

1509

``

`-

@fails_with_expat_2_6_0

`

1510

1507

`def test_simple_xml_chunk_1(self):

`

1511

``

`-

self.test_simple_xml(chunk_size=1)

`

``

1508

`+

self.test_simple_xml(chunk_size=1, flush=True)

`

1512

1509

``

1513

``

`-

@fails_with_expat_2_6_0

`

1514

1510

`def test_simple_xml_chunk_5(self):

`

1515

``

`-

self.test_simple_xml(chunk_size=5)

`

``

1511

`+

self.test_simple_xml(chunk_size=5, flush=True)

`

1516

1512

``

1517

1513

`def test_simple_xml_chunk_22(self):

`

1518

1514

`self.test_simple_xml(chunk_size=22)

`

`@@ -1711,6 +1707,57 @@ def test_unknown_event(self):

`

1711

1707

`with self.assertRaises(ValueError):

`

1712

1708

`ET.XMLPullParser(events=('start', 'end', 'bogus'))

`

1713

1709

``

``

1710

`+

def test_flush_reparse_deferral_enabled(self):

`

``

1711

`+

if pyexpat.version_info < (2, 6, 0):

`

``

1712

`+

self.skipTest(f'Expat {pyexpat.version_info} does not '

`

``

1713

`+

'support reparse deferral')

`

``

1714

+

``

1715

`+

parser = ET.XMLPullParser(events=('start', 'end'))

`

``

1716

+

``

1717

`+

for chunk in ("<doc", ">"):

`

``

1718

`+

parser.feed(chunk)

`

``

1719

+

``

1720

`+

self.assert_event_tags(parser, []) # i.e. no elements started

`

``

1721

`+

if ET is pyET:

`

``

1722

`+

self.assertTrue(parser._parser._parser.GetReparseDeferralEnabled())

`

``

1723

+

``

1724

`+

parser.flush()

`

``

1725

+

``

1726

`+

self.assert_event_tags(parser, [('start', 'doc')])

`

``

1727

`+

if ET is pyET:

`

``

1728

`+

self.assertTrue(parser._parser._parser.GetReparseDeferralEnabled())

`

``

1729

+

``

1730

`+

parser.feed("")

`

``

1731

`+

parser.close()

`

``

1732

+

``

1733

`+

self.assert_event_tags(parser, [('end', 'doc')])

`

``

1734

+

``

1735

`+

def test_flush_reparse_deferral_disabled(self):

`

``

1736

`+

parser = ET.XMLPullParser(events=('start', 'end'))

`

``

1737

+

``

1738

`+

for chunk in ("<doc", ">"):

`

``

1739

`+

parser.feed(chunk)

`

``

1740

+

``

1741

`+

if pyexpat.version_info >= (2, 6, 0):

`

``

1742

`+

if not ET is pyET:

`

``

1743

`+

self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled '

`

``

1744

`+

'methods not available in C')

`

``

1745

`+

parser._parser._parser.SetReparseDeferralEnabled(False)

`

``

1746

+

``

1747

`+

self.assert_event_tags(parser, []) # i.e. no elements started

`

``

1748

`+

if ET is pyET:

`

``

1749

`+

self.assertFalse(parser._parser._parser.GetReparseDeferralEnabled())

`

``

1750

+

``

1751

`+

parser.flush()

`

``

1752

+

``

1753

`+

self.assert_event_tags(parser, [('start', 'doc')])

`

``

1754

`+

if ET is pyET:

`

``

1755

`+

self.assertFalse(parser._parser._parser.GetReparseDeferralEnabled())

`

``

1756

+

``

1757

`+

parser.feed("")

`

``

1758

`+

parser.close()

`

``

1759

+

``

1760

`+

self.assert_event_tags(parser, [('end', 'doc')])

`

1714

1761

``

1715

1762

`#

`

1716

1763

`# xinclude tests (samples from appendix C of the xinclude specification)

`