1010import traceback
1111from io import BytesIO
1212from test import support
13- from test .support import os_helper
13+ from test .support import import_helper , os_helper
1414from test .support import sortdict
1515from unittest import mock
1616from xml .parsers import expat
@@ -825,7 +825,7 @@ def start_element(name, _):
825825
826826class AttackProtectionTest (unittest .TestCase ):
827827
828- def billion_laughs (self , ncols , nrows , text = '.' ):
828+ def billion_laughs (self , ncols , nrows , text = '.' , indent = ' ' ):
829829 """Create a billion laugh payload.
830830
831831 Be careful: the number of total items is pow(n, k), thereby
@@ -834,34 +834,36 @@ def billion_laughs(self, ncols, nrows, text='.'):
834834 body = textwrap .indent ('\n ' .join (
835835 f'<!ENTITY row{ i + 1 } "{ f"&row{ i } ;" * ncols } ">'
836836 for i in range (nrows )
837- ), ' ' )
837+ ), indent )
838838 return f"""\
839839 <?xml version="1.0"?>
840840<!DOCTYPE doc [
841- <!ENTITY row0 "{ text } ">
842- <!ELEMENT doc (#PCDATA)>
841+ { indent } <!ENTITY row0 "{ text } ">
842+ { indent } <!ELEMENT doc (#PCDATA)>
843843{ body }
844844]>
845845<doc>&row{ nrows } ;</doc>
846846"""
847847
848848 def test_set_alloc_tracker_maximum_amplification (self ):
849- payload = self .billion_laughs (10 , 4 )
849+ # On WASI, the maximum amplification factor of the payload may differ,
850+ # so we craft a payload that is likely to yield an allocation factor
851+ # way larger than 1.0 and way smaller than 10^5.
852+ payload = self .billion_laughs (1 , 2 )
850853
851854 p = expat .ParserCreate ()
852855 # Unconditionally enable maximum amplification factor.
853856 p .SetAllocTrackerActivationThreshold (0 )
854- # At runtime, the peak amplification factor is 101.71,
855- # which is above the default threshold (100.0).
856- msg = re . escape ( "out of memory: line 3 , column 15" )
857+ # Use a max amplification factor likely to be below the real one.
858+ self . assertIsNone ( p . SetAllocTrackerMaximumAmplification ( 1.0 ))
859+ msg = r "out of memory: line \d+ , column \d+"
857860 self .assertRaisesRegex (expat .ExpatError , msg , p .Parse , payload )
858861
859862 # # Re-create a parser as the current parser is now in an error state.
860863 p = expat .ParserCreate ()
861864 # Unconditionally enable maximum amplification factor.
862865 p .SetAllocTrackerActivationThreshold (0 )
863- # Use a max amplification factor a bit above the actual one.
864- self .assertIsNone (p .SetAllocTrackerMaximumAmplification (101.72 ))
866+ self .assertIsNone (p .SetAllocTrackerMaximumAmplification (10_000 ))
865867 self .assertIsNotNone (p .Parse (payload ))
866868
867869 def test_set_alloc_tracker_maximum_amplification_invalid_args (self ):
@@ -894,20 +896,21 @@ def test_set_alloc_tracker_activation_threshold(self):
894896 p .SetAllocTrackerActivationThreshold (MIN_ALLOC - 1 )
895897 # Check that we always reach the activation threshold.
896898 self .assertIsNone (p .SetAllocTrackerMaximumAmplification (1.0 ))
897- msg = re . escape ( "out of memory: line 3 , column 10" )
899+ msg = r "out of memory: line \d+ , column \d+"
898900 self .assertRaisesRegex (expat .ExpatError , msg , p .Parse , payload )
899901
900- def test_set_alloc_tracker_activation_threshold_invalid_args (self ):
902+ def test_set_alloc_tracker_activation_threshold_overflown_args (self ):
903+ _testcapi = import_helper .import_module ("_testcapi" )
901904 parser = expat .ParserCreate ()
902905 f = parser .SetAllocTrackerActivationThreshold
906+ self .assertRaises (OverflowError , f , _testcapi .ULLONG_MAX + 1 )
903907
904- ULONG_LONG_MAX = 2 * sys .maxsize + 1
905- self .assertRaises (OverflowError , f , ULONG_LONG_MAX + 1 )
906-
908+ def test_set_alloc_tracker_activation_threshold_invalid_args (self ):
909+ parser = expat .ParserCreate ()
907910 subparser = parser .ExternalEntityParserCreate (None )
908- fsub = subparser .SetAllocTrackerActivationThreshold
911+ f = subparser .SetAllocTrackerActivationThreshold
909912 msg = re .escape ("parser must be a root parser" )
910- self .assertRaisesRegex (expat .ExpatError , msg , fsub , 12345 )
913+ self .assertRaisesRegex (expat .ExpatError , msg , f , 12345 )
911914
912915
913916if __name__ == "__main__" :
0 commit comments