44import binascii
55import array
66import re
7+ from test .support import bigmemtest , _1G , _4G , warnings_helper
8+
79
810# Note: "*_hex" functions are aliases for "(un)hexlify"
9- b2a_functions = ['b2a_base64' , 'b2a_hex' , 'b2a_hqx' , ' b2a_qp' , 'b2a_uu' ,
10- 'hexlify' , 'rlecode_hqx' ]
11- a2b_functions = ['a2b_base64' , 'a2b_hex' , 'a2b_hqx' , ' a2b_qp' , 'a2b_uu' ,
12- 'unhexlify' , 'rledecode_hqx' ]
11+ b2a_functions = ['b2a_base64' , 'b2a_hex' , 'b2a_qp' , 'b2a_uu' ,
12+ 'hexlify' ]
13+ a2b_functions = ['a2b_base64' , 'a2b_hex' , 'a2b_qp' , 'a2b_uu' ,
14+ 'unhexlify' ]
1315all_functions = a2b_functions + b2a_functions + ['crc32' , 'crc_hqx' ]
1416
1517
@@ -30,8 +32,6 @@ def test_exceptions(self):
3032 self .assertTrue (issubclass (binascii .Error , Exception ))
3133 self .assertTrue (issubclass (binascii .Incomplete , Exception ))
3234
33- # TODO: RUSTPYTHON
34- @unittest .expectedFailure
3535 def test_functions (self ):
3636 # Check presence of all functions
3737 for name in all_functions :
@@ -52,9 +52,6 @@ def test_returned_value(self):
5252 res = a2b (self .type2test (a ))
5353 except Exception as err :
5454 self .fail ("{}/{} conversion raises {!r}" .format (fb , fa , err ))
55- if fb == 'b2a_hqx' :
56- # b2a_hqx returns a tuple
57- res , _ = res
5855 self .assertEqual (res , raw , "{}/{} conversion: "
5956 "{!r} != {!r}" .format (fb , fa , res , raw ))
6057 self .assertIsInstance (res , bytes )
@@ -117,6 +114,51 @@ def addnoise(line):
117114 # empty strings. TBD: shouldn't it raise an exception instead ?
118115 self .assertEqual (binascii .a2b_base64 (self .type2test (fillers )), b'' )
119116
117+ # TODO: RUSTPYTHON
118+ @unittest .expectedFailure
119+ def test_base64_strict_mode (self ):
120+ # Test base64 with strict mode on
121+ def _assertRegexTemplate (assert_regex : str , data : bytes , non_strict_mode_expected_result : bytes ):
122+ with self .assertRaisesRegex (binascii .Error , assert_regex ):
123+ binascii .a2b_base64 (self .type2test (data ), strict_mode = True )
124+ self .assertEqual (binascii .a2b_base64 (self .type2test (data ), strict_mode = False ),
125+ non_strict_mode_expected_result )
126+ self .assertEqual (binascii .a2b_base64 (self .type2test (data )),
127+ non_strict_mode_expected_result )
128+
129+ def assertExcessData (data , non_strict_mode_expected_result : bytes ):
130+ _assertRegexTemplate (r'(?i)Excess data' , data , non_strict_mode_expected_result )
131+
132+ def assertNonBase64Data (data , non_strict_mode_expected_result : bytes ):
133+ _assertRegexTemplate (r'(?i)Only base64 data' , data , non_strict_mode_expected_result )
134+
135+ def assertLeadingPadding (data , non_strict_mode_expected_result : bytes ):
136+ _assertRegexTemplate (r'(?i)Leading padding' , data , non_strict_mode_expected_result )
137+
138+ def assertDiscontinuousPadding (data , non_strict_mode_expected_result : bytes ):
139+ _assertRegexTemplate (r'(?i)Discontinuous padding' , data , non_strict_mode_expected_result )
140+
141+ # Test excess data exceptions
142+ assertExcessData (b'ab==a' , b'i' )
143+ assertExcessData (b'ab===' , b'i' )
144+ assertExcessData (b'ab==:' , b'i' )
145+ assertExcessData (b'abc=a' , b'i\xb7 ' )
146+ assertExcessData (b'abc=:' , b'i\xb7 ' )
147+ assertExcessData (b'ab==\n ' , b'i' )
148+
149+ # Test non-base64 data exceptions
150+ assertNonBase64Data (b'\n ab==' , b'i' )
151+ assertNonBase64Data (b'ab:(){:|:&};:==' , b'i' )
152+ assertNonBase64Data (b'a\n b==' , b'i' )
153+ assertNonBase64Data (b'a\x00 b==' , b'i' )
154+
155+ # Test malformed padding
156+ assertLeadingPadding (b'=' , b'' )
157+ assertLeadingPadding (b'==' , b'' )
158+ assertLeadingPadding (b'===' , b'' )
159+ assertDiscontinuousPadding (b'ab=c=' , b'i\xb7 ' )
160+ assertDiscontinuousPadding (b'ab=ab==' , b'i\xb6 \x9b ' )
161+
120162 # TODO: RUSTPYTHON
121163 @unittest .expectedFailure
122164 def test_base64errors (self ):
@@ -208,32 +250,6 @@ def test_crc32(self):
208250
209251 self .assertRaises (TypeError , binascii .crc32 )
210252
211- # TODO: RUSTPYTHON
212- @unittest .expectedFailure
213- def test_hqx (self ):
214- # Perform binhex4 style RLE-compression
215- # Then calculate the hexbin4 binary-to-ASCII translation
216- rle = binascii .rlecode_hqx (self .data )
217- a = binascii .b2a_hqx (self .type2test (rle ))
218-
219- b , _ = binascii .a2b_hqx (self .type2test (a ))
220- res = binascii .rledecode_hqx (b )
221- self .assertEqual (res , self .rawdata )
222-
223- def test_rle (self ):
224- # test repetition with a repetition longer than the limit of 255
225- data = (b'a' * 100 + b'b' + b'c' * 300 )
226-
227- encoded = binascii .rlecode_hqx (data )
228- self .assertEqual (encoded ,
229- (b'a\x90 d' # 'a' * 100
230- b'b' # 'b'
231- b'c\x90 \xff ' # 'c' * 255
232- b'c\x90 -' )) # 'c' * 45
233-
234- decoded = binascii .rledecode_hqx (encoded )
235- self .assertEqual (decoded , data )
236-
237253 def test_hex (self ):
238254 # test hexlification
239255 s = b'{s\005 \000 \000 \000 worldi\002 \000 \000 \000 s\005 \000 \000 \000 helloi\001 \000 \000 \000 0'
@@ -368,8 +384,6 @@ def test_qp(self):
368384 self .assertEqual (b2a_qp (type2test (b'a.\n ' )), b'a.\n ' )
369385 self .assertEqual (b2a_qp (type2test (b'.a' )[:- 1 ]), b'=2E' )
370386
371- # TODO: RUSTPYTHON
372- @unittest .expectedFailure
373387 def test_empty_string (self ):
374388 # A test for SF bug #1022953. Make sure SystemError is not raised.
375389 empty = self .type2test (b'' )
@@ -388,7 +402,7 @@ def test_empty_string(self):
388402 @unittest .expectedFailure
389403 def test_unicode_b2a (self ):
390404 # Unicode strings are not accepted by b2a_* functions.
391- for func in set (all_functions ) - set (a2b_functions ) | { 'rledecode_hqx' } :
405+ for func in set (all_functions ) - set (a2b_functions ):
392406 try :
393407 self .assertRaises (TypeError , getattr (binascii , func ), "test" )
394408 except Exception as err :
@@ -403,9 +417,6 @@ def test_unicode_a2b(self):
403417 MAX_ALL = 45
404418 raw = self .rawdata [:MAX_ALL ]
405419 for fa , fb in zip (a2b_functions , b2a_functions ):
406- if fa == 'rledecode_hqx' :
407- # Takes non-ASCII data
408- continue
409420 a2b = getattr (binascii , fa )
410421 b2a = getattr (binascii , fb )
411422 try :
@@ -415,10 +426,6 @@ def test_unicode_a2b(self):
415426 res = a2b (a )
416427 except Exception as err :
417428 self .fail ("{}/{} conversion raises {!r}" .format (fb , fa , err ))
418- if fb == 'b2a_hqx' :
419- # b2a_hqx returns a tuple
420- res , _ = res
421- binary_res , _ = binary_res
422429 self .assertEqual (res , raw , "{}/{} conversion: "
423430 "{!r} != {!r}" .format (fb , fa , res , raw ))
424431 self .assertEqual (res , binary_res )
@@ -449,6 +456,14 @@ class BytearrayBinASCIITest(BinASCIITest):
449456class MemoryviewBinASCIITest (BinASCIITest ):
450457 type2test = memoryview
451458
459+ class ChecksumBigBufferTestCase (unittest .TestCase ):
460+ """bpo-38256 - check that inputs >=4 GiB are handled correctly."""
461+
462+ @bigmemtest (size = _4G + 4 , memuse = 1 , dry_run = False )
463+ def test_big_buffer (self , size ):
464+ data = b"nyan" * (_1G + 1 )
465+ self .assertEqual (binascii .crc32 (data ), 1044521549 )
466+
452467
453468if __name__ == "__main__" :
454469 unittest .main ()
0 commit comments