Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions Lib/base64.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,27 @@ def b64decode(s, altchars=None, validate=False):
https://docs.python.org/3.11/library/binascii.html#binascii.a2b_base64
"""
s = _bytes_from_decode_data(s)
badchar = None
if altchars is not None:
altchars = _bytes_from_decode_data(altchars)
assert len(altchars) == 2, repr(altchars)
s = s.translate(bytes.maketrans(altchars, b'+/'))
return binascii.a2b_base64(s, strict_mode=validate)
if len(altchars) != 2:
raise ValueError(f'invalid altchars: {altchars!r}')
if validate:
s = s.translate(bytes.maketrans(b'+/' + altchars, altchars + b'+/'))
else:
for b in set(b'+/') - set(altchars):
if b in s:
badchar = b
break
s = s.translate(bytes.maketrans(altchars, b'+/'))
result = binascii.a2b_base64(s, strict_mode=validate)
if badchar is not None:
import warnings
warnings.warn(f'invalid character {chr(badchar)!a} in base64 data '
f'with altchars={altchars!r} will be discarded in '
f'future Python versions',
FutureWarning, stacklevel=2)
return result


def standard_b64encode(s):
Expand All @@ -104,7 +120,7 @@ def standard_b64decode(s):


_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_')
_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/')
_urlsafe_decode_translation = bytes.maketrans(b'+/-_', b'-_+/')

def urlsafe_b64encode(s):
"""Encode bytes using the URL- and filesystem-safe Base64 alphabet.
Expand Down
27 changes: 20 additions & 7 deletions Lib/test/test_base64.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ def test_b64decode_altchars(self):
eq(base64.b64decode(data, altchars=altchars_str), res)
eq(base64.b64decode(data_str, altchars=altchars_str), res)

self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+')
self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+/-')
self.assertRaises(ValueError, base64.b64decode, '', altchars='+')
self.assertRaises(ValueError, base64.b64decode, '', altchars='+/-')

def test_b64decode_padding_error(self):
self.assertRaises(binascii.Error, base64.b64decode, b'abc')
self.assertRaises(binascii.Error, base64.b64decode, 'abc')
Expand Down Expand Up @@ -296,13 +301,21 @@ def test_b64decode_invalid_chars(self):
with self.assertRaises(binascii.Error):
base64.b64decode(bstr.decode('ascii'), validate=True)

# Normal alphabet characters not discarded when alternative given
res = b'\xfb\xef\xff'
self.assertEqual(base64.b64decode(b'++//', validate=True), res)
self.assertEqual(base64.b64decode(b'++//', '-_', validate=True), res)
self.assertEqual(base64.b64decode(b'--__', '-_', validate=True), res)
self.assertEqual(base64.urlsafe_b64decode(b'++//'), res)
self.assertEqual(base64.urlsafe_b64decode(b'--__'), res)
# Normal alphabet characters will be discarded when alternative given
with self.assertWarns(FutureWarning):
self.assertEqual(base64.b64decode(b'++++', altchars=b'-_'),
b'\xfb\xef\xbe')
with self.assertWarns(FutureWarning):
self.assertEqual(base64.b64decode(b'////', altchars=b'-_'),
b'\xff\xff\xff')
self.assertEqual(base64.urlsafe_b64decode(b'++++'), b'')
self.assertEqual(base64.urlsafe_b64decode(b'////'), b'')
with self.assertRaises(binascii.Error):
base64.b64decode(b'++++', altchars=b'-_', validate=True)
with self.assertRaises(binascii.Error):
base64.b64decode(b'////', altchars=b'-_', validate=True)
with self.assertRaises(binascii.Error):
base64.b64decode(b'+/!', altchars=b'-_')

def _altchars_strategy():
"""Generate 'altchars' for base64 encoding."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The ``+`` and ``/`` characters are no longer recognized as the part of the
Base64 alphabet in :func:`base64.urlsafe_b64decode` and
:func:`base64.b64decode` with the *altchars* argument that does not contain
them.
Loading