@@ -98,30 +98,42 @@ def len_q(bstring):
9898#
9999
100100def decode_b (encoded ):
101- defects = []
101+ # First try encoding with validate=True, fixing the padding if needed.
102+ # This will succeed only if encoded includes no invalid characters.
102103 pad_err = len (encoded ) % 4
103- if pad_err :
104- defects .append (errors .InvalidBase64PaddingDefect ())
105- padded_encoded = encoded + b'===' [:4 - pad_err ]
106- else :
107- padded_encoded = encoded
104+ missing_padding = b'===' [:4 - pad_err ] if pad_err else b''
108105 try :
109- return base64 .b64decode (padded_encoded , validate = True ), defects
106+ return (
107+ base64 .b64decode (encoded + missing_padding , validate = True ),
108+ [errors .InvalidBase64PaddingDefect ()] if pad_err else [],
109+ )
110110 except binascii .Error :
111- # Since we had correct padding, this must an invalid char error.
112- defects = [ errors . InvalidBase64CharactersDefect ()]
111+ # Since we had correct padding, this is likely an invalid char error.
112+ #
113113 # The non-alphabet characters are ignored as far as padding
114- # goes, but we don't know how many there are. So we'll just
115- # try various padding lengths until something works.
116- for i in 0 , 1 , 2 , 3 :
114+ # goes, but we don't know how many there are. So try without adding
115+ # padding to see if it works.
116+ try :
117+ return (
118+ base64 .b64decode (encoded , validate = False ),
119+ [errors .InvalidBase64CharactersDefect ()],
120+ )
121+ except binascii .Error :
122+ # Add as much padding as could possibly be necessary (extra padding
123+ # is ignored).
117124 try :
118- return base64 .b64decode (encoded + b'=' * i , validate = False ), defects
125+ return (
126+ base64 .b64decode (encoded + b'==' , validate = False ),
127+ [errors .InvalidBase64CharactersDefect (),
128+ errors .InvalidBase64PaddingDefect ()],
129+ )
119130 except binascii .Error :
120- if i == 0 :
121- defects .append (errors .InvalidBase64PaddingDefect ())
122- else :
123- # This should never happen.
124- raise AssertionError ("unexpected binascii.Error" )
131+ # This only happens when the encoded string's length is 1 more
132+ # than a multiple of 4, which is invalid.
133+ #
134+ # bpo-27397: Just return the encoded string since there's no
135+ # way to decode.
136+ return encoded , [errors .InvalidBase64LengthDefect ()]
125137
126138def encode_b (bstring ):
127139 return base64 .b64encode (bstring ).decode ('ascii' )
0 commit comments