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
@@ -52,9 +54,6 @@ def test_returned_value(self):
5254 res = a2b (self .type2test (a ))
5355 except Exception as err :
5456 self .fail ("{}/{} conversion raises {!r}" .format (fb , fa , err ))
55- if fb == 'b2a_hqx' :
56- # b2a_hqx returns a tuple
57- res , _ = res
5857 self .assertEqual (res , raw , "{}/{} conversion: "
5958 "{!r} != {!r}" .format (fb , fa , res , raw ))
6059 self .assertIsInstance (res , bytes )
@@ -117,6 +116,49 @@ def addnoise(line):
117116 # empty strings. TBD: shouldn't it raise an exception instead ?
118117 self .assertEqual (binascii .a2b_base64 (self .type2test (fillers )), b'' )
119118
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'
@@ -388,7 +404,7 @@ def test_empty_string(self):
388404 @unittest .expectedFailure
389405 def test_unicode_b2a (self ):
390406 # Unicode strings are not accepted by b2a_* functions.
391- for func in set (all_functions ) - set (a2b_functions ) | { 'rledecode_hqx' } :
407+ for func in set (all_functions ) - set (a2b_functions ):
392408 try :
393409 self .assertRaises (TypeError , getattr (binascii , func ), "test" )
394410 except Exception as err :
@@ -403,9 +419,6 @@ def test_unicode_a2b(self):
403419 MAX_ALL = 45
404420 raw = self .rawdata [:MAX_ALL ]
405421 for fa , fb in zip (a2b_functions , b2a_functions ):
406- if fa == 'rledecode_hqx' :
407- # Takes non-ASCII data
408- continue
409422 a2b = getattr (binascii , fa )
410423 b2a = getattr (binascii , fb )
411424 try :
@@ -415,10 +428,6 @@ def test_unicode_a2b(self):
415428 res = a2b (a )
416429 except Exception as err :
417430 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
422431 self .assertEqual (res , raw , "{}/{} conversion: "
423432 "{!r} != {!r}" .format (fb , fa , res , raw ))
424433 self .assertEqual (res , binary_res )
@@ -449,6 +458,14 @@ class BytearrayBinASCIITest(BinASCIITest):
449458class MemoryviewBinASCIITest (BinASCIITest ):
450459 type2test = memoryview
451460
461+ class ChecksumBigBufferTestCase (unittest .TestCase ):
462+ """bpo-38256 - check that inputs >=4 GiB are handled correctly."""
463+
464+ @bigmemtest (size = _4G + 4 , memuse = 1 , dry_run = False )
465+ def test_big_buffer (self , size ):
466+ data = b"nyan" * (_1G + 1 )
467+ self .assertEqual (binascii .crc32 (data ), 1044521549 )
468+
452469
453470if __name__ == "__main__" :
454471 unittest .main ()
0 commit comments