@@ -118,66 +118,77 @@ def addnoise(line):
118118 # empty strings. TBD: shouldn't it raise an exception instead ?
119119 self .assertEqual (binascii .a2b_base64 (self .type2test (fillers )), b'' )
120120
121- def test_base64_strict_mode (self ):
122- # Test base64 with strict mode on
123- def _assertRegexTemplate (assert_regex : str , data : bytes , non_strict_mode_expected_result : bytes ):
121+ def test_base64_bad_padding (self ):
122+ # Test malformed padding
123+ def _assertRegexTemplate (assert_regex , data , non_strict_mode_expected_result ):
124+ data = self .type2test (data )
124125 with self .assertRaisesRegex (binascii .Error , assert_regex ):
125- binascii .a2b_base64 (self . type2test ( data ) , strict_mode = True )
126- self .assertEqual (binascii .a2b_base64 (self . type2test ( data ) , strict_mode = False ),
126+ binascii .a2b_base64 (data , strict_mode = True )
127+ self .assertEqual (binascii .a2b_base64 (data , strict_mode = False ),
127128 non_strict_mode_expected_result )
128- self .assertEqual (binascii .a2b_base64 (self .type2test (data )),
129+ self .assertEqual (binascii .a2b_base64 (data , strict_mode = True ,
130+ ignorechars = b'=' ),
131+ non_strict_mode_expected_result )
132+ self .assertEqual (binascii .a2b_base64 (data ),
129133 non_strict_mode_expected_result )
130134
131- def assertExcessData (data , non_strict_mode_expected_result : bytes ):
132- _assertRegexTemplate (r'(?i)Excess data' , data , non_strict_mode_expected_result )
133-
134- def assertNonBase64Data (data , non_strict_mode_expected_result : bytes ):
135- _assertRegexTemplate (r'(?i)Only base64 data' , data , non_strict_mode_expected_result )
135+ def assertLeadingPadding (* args ):
136+ _assertRegexTemplate (r'(?i)Leading padding' , * args )
136137
137- def assertLeadingPadding ( data , non_strict_mode_expected_result : bytes ):
138- _assertRegexTemplate (r'(?i)Leading padding' , data , non_strict_mode_expected_result )
138+ def assertDiscontinuousPadding ( * args ):
139+ _assertRegexTemplate (r'(?i)Discontinuous padding' , * args )
139140
140- def assertDiscontinuousPadding ( data , non_strict_mode_expected_result : bytes ):
141- _assertRegexTemplate (r'(?i)Discontinuous padding' , data , non_strict_mode_expected_result )
141+ def assertExcessPadding ( * args ):
142+ _assertRegexTemplate (r'(?i)Excess padding' , * args )
142143
143- def assertExcessPadding ( data , non_strict_mode_expected_result : bytes ):
144- _assertRegexTemplate (r'(?i)Excess padding' , data , non_strict_mode_expected_result )
144+ def assertInvalidLength ( * args ):
145+ _assertRegexTemplate (r'(?i)Invalid.+number of data characters' , * args )
145146
146- # Test excess data exceptions
147- assertExcessData (b'ab==a' , b'i' )
148147 assertExcessPadding (b'ab===' , b'i' )
149148 assertExcessPadding (b'ab====' , b'i' )
150- assertNonBase64Data (b'ab==:' , b'i' )
151- assertExcessData (b'abc=a' , b'i\xb7 ' )
152- assertNonBase64Data (b'abc=:' , b'i\xb7 ' )
153- assertNonBase64Data (b'ab==\n ' , b'i' )
154149 assertExcessPadding (b'abc==' , b'i\xb7 ' )
155150 assertExcessPadding (b'abc===' , b'i\xb7 ' )
156151 assertExcessPadding (b'abc====' , b'i\xb7 ' )
157152 assertExcessPadding (b'abc=====' , b'i\xb7 ' )
158153
159- # Test non-base64 data exceptions
160- assertNonBase64Data (b'\n ab==' , b'i' )
161- assertNonBase64Data (b'ab:(){:|:&};:==' , b'i' )
162- assertNonBase64Data (b'a\n b==' , b'i' )
163- assertNonBase64Data (b'a\x00 b==' , b'i' )
164-
165- # Test malformed padding
166154 assertLeadingPadding (b'=' , b'' )
167155 assertLeadingPadding (b'==' , b'' )
168156 assertLeadingPadding (b'===' , b'' )
169157 assertLeadingPadding (b'====' , b'' )
170158 assertLeadingPadding (b'=====' , b'' )
159+ assertLeadingPadding (b'=abcd' , b'i\xb7 \x1d ' )
160+ assertLeadingPadding (b'==abcd' , b'i\xb7 \x1d ' )
161+ assertLeadingPadding (b'===abcd' , b'i\xb7 \x1d ' )
162+ assertLeadingPadding (b'====abcd' , b'i\xb7 \x1d ' )
163+ assertLeadingPadding (b'=====abcd' , b'i\xb7 \x1d ' )
164+
165+ assertInvalidLength (b'a=b==' , b'i' )
166+ assertInvalidLength (b'a=bc=' , b'i\xb7 ' )
167+ assertInvalidLength (b'a=bc==' , b'i\xb7 ' )
168+ assertInvalidLength (b'a=bcd' , b'i\xb7 \x1d ' )
169+ assertInvalidLength (b'a=bcd=' , b'i\xb7 \x1d ' )
170+
171171 assertDiscontinuousPadding (b'ab=c=' , b'i\xb7 ' )
172- assertDiscontinuousPadding (b'ab=ab==' , b'i\xb6 \x9b ' )
173- assertNonBase64Data (b'ab=:=' , b'i' )
172+ assertDiscontinuousPadding (b'ab=cd' , b'i\xb7 \x1d ' )
173+ assertDiscontinuousPadding (b'ab=cd==' , b'i\xb7 \x1d ' )
174+
174175 assertExcessPadding (b'abcd=' , b'i\xb7 \x1d ' )
175176 assertExcessPadding (b'abcd==' , b'i\xb7 \x1d ' )
176177 assertExcessPadding (b'abcd===' , b'i\xb7 \x1d ' )
177178 assertExcessPadding (b'abcd====' , b'i\xb7 \x1d ' )
178179 assertExcessPadding (b'abcd=====' , b'i\xb7 \x1d ' )
180+ assertExcessPadding (b'abcd==' , b'i\xb7 \x1d ' )
181+ assertExcessPadding (b'abcd===' , b'i\xb7 \x1d ' )
182+ assertExcessPadding (b'abcd====' , b'i\xb7 \x1d ' )
183+ assertExcessPadding (b'abcd=====' , b'i\xb7 \x1d ' )
184+ assertExcessPadding (b'abcd=efgh' , b'i\xb7 \x1d y\xf8 !' )
185+ assertExcessPadding (b'abcd==efgh' , b'i\xb7 \x1d y\xf8 !' )
186+ assertExcessPadding (b'abcd===efgh' , b'i\xb7 \x1d y\xf8 !' )
187+ assertExcessPadding (b'abcd====efgh' , b'i\xb7 \x1d y\xf8 !' )
188+ assertExcessPadding (b'abcd=====efgh' , b'i\xb7 \x1d y\xf8 !' )
179189
180190 def test_base64_invalidchars (self ):
191+ # Test non-base64 data exceptions
181192 def assertNonBase64Data (data , expected , ignorechars ):
182193 data = self .type2test (data )
183194 assert_regex = r'(?i)Only base64 data'
@@ -195,10 +206,11 @@ def assertNonBase64Data(data, expected, ignorechars):
195206 assertNonBase64Data (b'ab:(){:|:&};:==' , b'i' , ignorechars = b':;(){}|&' )
196207 assertNonBase64Data (b'a\n b==' , b'i' , ignorechars = b'\n ' )
197208 assertNonBase64Data (b'a\x00 b==' , b'i' , ignorechars = b'\x00 ' )
209+ assertNonBase64Data (b'ab:==' , b'i' , ignorechars = b':' )
210+ assertNonBase64Data (b'ab=:=' , b'i' , ignorechars = b':' )
198211 assertNonBase64Data (b'ab==:' , b'i' , ignorechars = b':' )
199212 assertNonBase64Data (b'abc=:' , b'i\xb7 ' , ignorechars = b':' )
200213 assertNonBase64Data (b'ab==\n ' , b'i' , ignorechars = b'\n ' )
201- assertNonBase64Data (b'ab=:=' , b'i' , ignorechars = b':' )
202214 assertNonBase64Data (b'a\n b==' , b'i' , ignorechars = bytearray (b'\n ' ))
203215 assertNonBase64Data (b'a\n b==' , b'i' , ignorechars = memoryview (b'\n ' ))
204216
@@ -210,36 +222,67 @@ def assertNonBase64Data(data, expected, ignorechars):
210222 with self .assertRaises (TypeError ):
211223 binascii .a2b_base64 (data , ignorechars = None )
212224
225+ def test_base64_excess_data (self ):
226+ # Test excess data exceptions
227+ def assertExcessData (data , non_strict_expected , ignore_padchar_expected = None ):
228+ assert_regex = r'(?i)Excess data'
229+ data = self .type2test (data )
230+ with self .assertRaisesRegex (binascii .Error , assert_regex ):
231+ binascii .a2b_base64 (data , strict_mode = True )
232+ self .assertEqual (binascii .a2b_base64 (data , strict_mode = False ),
233+ non_strict_expected )
234+ if ignore_padchar_expected is not None :
235+ self .assertEqual (binascii .a2b_base64 (data , strict_mode = True ,
236+ ignorechars = b'=' ),
237+ ignore_padchar_expected )
238+ self .assertEqual (binascii .a2b_base64 (data ), non_strict_expected )
239+
240+ assertExcessData (b'ab==c' , b'i' )
241+ assertExcessData (b'ab==cd' , b'i' , b'i\xb7 \x1d ' )
242+ assertExcessData (b'abc=d' , b'i\xb7 ' , b'i\xb7 \x1d ' )
243+
213244 def test_base64errors (self ):
214245 # Test base64 with invalid padding
215- def assertIncorrectPadding (data ):
246+ def assertIncorrectPadding (data , strict_mode = True ):
247+ data = self .type2test (data )
216248 with self .assertRaisesRegex (binascii .Error , r'(?i)Incorrect padding' ):
217- binascii .a2b_base64 (self .type2test (data ))
249+ binascii .a2b_base64 (data )
250+ with self .assertRaisesRegex (binascii .Error , r'(?i)Incorrect padding' ):
251+ binascii .a2b_base64 (data , strict_mode = False )
252+ if strict_mode :
253+ with self .assertRaisesRegex (binascii .Error , r'(?i)Incorrect padding' ):
254+ binascii .a2b_base64 (data , strict_mode = True )
218255
219256 assertIncorrectPadding (b'ab' )
220257 assertIncorrectPadding (b'ab=' )
221258 assertIncorrectPadding (b'abc' )
222259 assertIncorrectPadding (b'abcdef' )
223260 assertIncorrectPadding (b'abcdef=' )
224261 assertIncorrectPadding (b'abcdefg' )
225- assertIncorrectPadding (b'a=b=' )
226- assertIncorrectPadding (b'a\n b=' )
262+ assertIncorrectPadding (b'a=b=' , strict_mode = False )
263+ assertIncorrectPadding (b'a\n b=' , strict_mode = False )
227264
228265 # Test base64 with invalid number of valid characters (1 mod 4)
229- def assertInvalidLength (data ):
266+ def assertInvalidLength (data , strict_mode = True ):
230267 n_data_chars = len (re .sub (br'[^A-Za-z0-9/+]' , br'' , data ))
268+ data = self .type2test (data )
231269 expected_errmsg_re = \
232270 r'(?i)Invalid.+number of data characters.+' + str (n_data_chars )
233271 with self .assertRaisesRegex (binascii .Error , expected_errmsg_re ):
234- binascii .a2b_base64 (self .type2test (data ))
272+ binascii .a2b_base64 (data )
273+ with self .assertRaisesRegex (binascii .Error , expected_errmsg_re ):
274+ binascii .a2b_base64 (data , strict_mode = False )
275+ if strict_mode :
276+ with self .assertRaisesRegex (binascii .Error , expected_errmsg_re ):
277+ binascii .a2b_base64 (data , strict_mode = True )
235278
236279 assertInvalidLength (b'a' )
237280 assertInvalidLength (b'a=' )
238281 assertInvalidLength (b'a==' )
239282 assertInvalidLength (b'a===' )
240283 assertInvalidLength (b'a' * 5 )
241284 assertInvalidLength (b'a' * (4 * 87 + 1 ))
242- assertInvalidLength (b'A\t B\n C ??DE' ) # only 5 valid characters
285+ assertInvalidLength (b'A\t B\n C ??DE' , strict_mode = False ) # only 5 valid characters
243286
244287 def test_uu (self ):
245288 MAX_UU = 45
0 commit comments