@@ -303,22 +303,26 @@ def test_b64decode_padding_error(self):
303303
304304 def test_b64decode_invalid_chars (self ):
305305 # issue 1466065: Test some invalid characters.
306- tests = ((b'%3d==' , b'\xdd ' ),
307- (b'$3d==' , b'\xdd ' ),
308- (b'[==' , b'' ),
309- (b'YW]3=' , b'am' ),
310- (b'3{d==' , b'\xdd ' ),
311- (b'3d}==' , b'\xdd ' ),
312- (b'@@' , b'' ),
313- (b'!' , b'' ),
314- (b"YWJj\n " , b"abc" ),
315- (b'YWJj\n YWI=' , b'abcab' ))
306+ tests = ((b'%3d==' , b'\xdd ' , b'%$' ),
307+ (b'$3d==' , b'\xdd ' , b'%$' ),
308+ (b'[==' , b'' , None ),
309+ (b'YW]3=' , b'am' , b']' ),
310+ (b'3{d==' , b'\xdd ' , b'{}' ),
311+ (b'3d}==' , b'\xdd ' , b'{}' ),
312+ (b'@@' , b'' , b'@!' ),
313+ (b'!' , b'' , b'@!' ),
314+ (b"YWJj\n " , b"abc" , b'\n ' ),
315+ (b'YWJj\n YWI=' , b'abcab' , b'\n ' ),
316+ (b'YW\n Jj' , b'abc' , b'\n ' ),
317+ (b'YW\n Jj' , b'abc' , bytearray (b'\n ' )),
318+ (b'YW\n Jj' , b'abc' , memoryview (b'\n ' )),
319+ )
316320 funcs = (
317321 base64 .b64decode ,
318322 base64 .standard_b64decode ,
319323 base64 .urlsafe_b64decode ,
320324 )
321- for bstr , res in tests :
325+ for bstr , res , ignorechars in tests :
322326 for func in funcs :
323327 with self .subTest (bstr = bstr , func = func ):
324328 self .assertEqual (func (bstr ), res )
@@ -327,24 +331,76 @@ def test_b64decode_invalid_chars(self):
327331 base64 .b64decode (bstr , validate = True )
328332 with self .assertRaises (binascii .Error ):
329333 base64 .b64decode (bstr .decode ('ascii' ), validate = True )
334+ with self .assertRaises (binascii .Error ):
335+ # Even empty ignorechars enables the strict mode.
336+ base64 .b64decode (bstr , ignorechars = b'' )
337+ if ignorechars is not None :
338+ r = base64 .b64decode (bstr , ignorechars = ignorechars )
339+ self .assertEqual (r , res )
340+
341+ with self .assertRaises (TypeError ):
342+ base64 .b64decode (b'' , ignorechars = '' )
343+ with self .assertRaises (TypeError ):
344+ base64 .b64decode (b'' , ignorechars = [])
345+ with self .assertRaises (TypeError ):
346+ base64 .b64decode (b'' , ignorechars = None )
330347
331348 # Normal alphabet characters will be discarded when alternative given
332- with self .assertWarns (FutureWarning ):
333- self .assertEqual (base64 .b64decode (b'++++' , altchars = b'-_' ),
334- b'\xfb \xef \xbe ' )
335- with self .assertWarns (FutureWarning ):
336- self .assertEqual (base64 .b64decode (b'////' , altchars = b'-_' ),
337- b'\xff \xff \xff ' )
338- with self .assertWarns (DeprecationWarning ):
339- self .assertEqual (base64 .b64decode (b'++++' , altchars = b'-_' , validate = True ),
340- b'\xfb \xef \xbe ' )
341- with self .assertWarns (DeprecationWarning ):
342- self .assertEqual (base64 .b64decode (b'////' , altchars = b'-_' , validate = True ),
343- b'\xff \xff \xff ' )
344- with self .assertWarns (FutureWarning ):
349+ discarded = ("invalid character %a in Base64 data with %s "
350+ "will be discarded in future Python versions" )
351+ error = ("invalid character %a in Base64 data with %s "
352+ "will be an error in future Python versions" )
353+ with self .assertWarns (FutureWarning ) as cm :
354+ r = base64 .b64decode (b'++++' , altchars = b'-_' )
355+ self .assertEqual (r , b'\xfb \xef \xbe ' )
356+ self .assertEqual (str (cm .warning ),
357+ discarded % ('+' , "altchars=b'-_' and validate=False" ))
358+ with self .assertWarns (FutureWarning ) as cm :
359+ r = base64 .b64decode (b'////' , altchars = b'-_' )
360+ self .assertEqual (r , b'\xff \xff \xff ' )
361+ self .assertEqual (str (cm .warning ),
362+ discarded % ('/' , "altchars=b'-_' and validate=False" ))
363+ with self .assertWarns (DeprecationWarning ) as cm :
364+ r = base64 .b64decode (b'++++' , altchars = b'-_' , validate = True )
365+ self .assertEqual (r , b'\xfb \xef \xbe ' )
366+ self .assertEqual (str (cm .warning ),
367+ error % ('+' , "altchars=b'-_' and validate=True" ))
368+ with self .assertWarns (DeprecationWarning ) as cm :
369+ r = base64 .b64decode (b'////' , altchars = b'-_' , validate = True )
370+ self .assertEqual (r , b'\xff \xff \xff ' )
371+ self .assertEqual (str (cm .warning ),
372+ error % ('/' , "altchars=b'-_' and validate=True" ))
373+ with self .assertWarns (FutureWarning ) as cm :
374+ r = base64 .b64decode (b'++++' , altchars = b'-_' , ignorechars = b'+' )
375+ self .assertEqual (r , b'\xfb \xef \xbe ' )
376+ self .assertEqual (str (cm .warning ),
377+ discarded % ('+' , "altchars=b'-_' and ignorechars=b'+'" ))
378+ with self .assertWarns (FutureWarning ) as cm :
379+ r = base64 .b64decode (b'////' , altchars = b'-_' , ignorechars = b'/' )
380+ self .assertEqual (r , b'\xff \xff \xff ' )
381+ self .assertEqual (str (cm .warning ),
382+ discarded % ('/' , "altchars=b'-_' and ignorechars=b'/'" ))
383+ with self .assertWarns (DeprecationWarning ) as cm :
384+ r = base64 .b64decode (b'++++////' , altchars = b'-_' , ignorechars = b'+' )
385+ self .assertEqual (r , b'\xfb \xef \xbe \xff \xff \xff ' )
386+ self .assertEqual (str (cm .warning ),
387+ error % ('/' , "altchars=b'-_' and validate=True" ))
388+ with self .assertWarns (DeprecationWarning ) as cm :
389+ r = base64 .b64decode (b'++++////' , altchars = b'-_' , ignorechars = b'/' )
390+ self .assertEqual (r , b'\xfb \xef \xbe \xff \xff \xff ' )
391+ self .assertEqual (str (cm .warning ),
392+ error % ('+' , "altchars=b'-_' and validate=True" ))
393+
394+ with self .assertWarns (FutureWarning ) as cm :
345395 self .assertEqual (base64 .urlsafe_b64decode (b'++++' ), b'\xfb \xef \xbe ' )
346- with self .assertWarns (FutureWarning ):
396+ self .assertEqual (str (cm .warning ),
397+ "invalid character '+' in URL-safe Base64 data "
398+ "will be discarded in future Python versions" )
399+ with self .assertWarns (FutureWarning ) as cm :
347400 self .assertEqual (base64 .urlsafe_b64decode (b'////' ), b'\xff \xff \xff ' )
401+ self .assertEqual (str (cm .warning ),
402+ "invalid character '/' in URL-safe Base64 data "
403+ "will be discarded in future Python versions" )
348404 with self .assertRaises (binascii .Error ):
349405 base64 .b64decode (b'+/!' , altchars = b'-_' )
350406
0 commit comments