Skip to content

Commit db32b32

Browse files
Make validate=True by default in base64.b64decode().
1 parent 0c8fe51 commit db32b32

6 files changed

Lines changed: 62 additions & 35 deletions

File tree

Doc/library/base64.rst

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ POST request.
6565
:exc:`TypeError` if *altchars* is not a :term:`bytes-like object`.
6666

6767

68-
.. function:: b64decode(s, altchars=None, validate=False)
68+
.. function:: b64decode(s, altchars=None, validate=True)
6969

7070
Decode the Base64 encoded :term:`bytes-like object` or ASCII string
7171
*s* and return the decoded :class:`bytes`.
@@ -77,15 +77,24 @@ POST request.
7777
A :exc:`binascii.Error` exception is raised
7878
if *s* is incorrectly padded.
7979

80-
If *validate* is ``False`` (the default), characters that are neither
81-
in the normal base-64 alphabet nor the alternative alphabet are
82-
discarded prior to the padding check. If *validate* is ``True``,
83-
these non-alphabet characters in the input result in a
80+
By default, non-alphabet characters in the input result in a
8481
:exc:`binascii.Error`.
82+
If *validate* is false, characters that are neither in the normal base-64
83+
alphabet nor the alternative alphabet are discarded prior to the padding
84+
check, but the ``+`` and ``/`` characters keep their meaning if they are
85+
not in *altchars* (they will be discarded in future Python versions).
8586

86-
For more information about the strict base64 check, see :func:`binascii.a2b_base64`
87+
For more information about the strict base64 check, see
88+
:func:`binascii.a2b_base64`.
89+
90+
.. versionchanged:: next
91+
*validate* is now ``True`` by default.
92+
The ``+`` and ``/`` characters no longer preserve their meaning if they
93+
are not in the alternative alphabet and *validate* is true.
94+
:exc:`FutureWarning` is now emitted if the ``+`` or ``/`` characters
95+
which are not in the alternative alphabet occur in the input and
96+
*validate* is false.
8797

88-
May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2.
8998

9099
.. function:: standard_b64encode(s)
91100

@@ -98,6 +107,9 @@ POST request.
98107
Decode :term:`bytes-like object` or ASCII string *s* using the standard
99108
Base64 alphabet and return the decoded :class:`bytes`.
100109

110+
.. versionchanged:: next
111+
Non-alphabet characters in the input result in a :exc:`binascii.Error`.
112+
101113

102114
.. function:: urlsafe_b64encode(s)
103115

@@ -116,6 +128,9 @@ POST request.
116128
``/`` in the standard Base64 alphabet, and return the decoded
117129
:class:`bytes`.
118130

131+
.. versionchanged:: next
132+
Non-alphabet characters in the input result in a :exc:`binascii.Error`.
133+
119134

120135
.. function:: b32encode(s)
121136

Doc/whatsnew/3.15.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,3 +1282,18 @@ that may require changes to your code.
12821282
*dest* is now ``'foo'`` instead of ``'f'``.
12831283
Pass an explicit *dest* argument to preserve the old behavior.
12841284
(Contributed by Serhiy Storchaka in :gh:`138697`.)
1285+
1286+
* :func:`base64.b64decode` now rejects all characters not in the base 64
1287+
alphabet by default.
1288+
You can pass the ``validate=False`` argument to get the old behavior.
1289+
If *validate* is false, :exc:`FutureWarning` is now emitted if the ``+`` or
1290+
``/`` characters which are not in the alternative alphabet occur in the input.
1291+
To get rid of the potential warnings, either replace these characters with
1292+
the corresponding alternative characters (to keep the old behavior),
1293+
or remove them from the input (to get the future behavior).
1294+
1295+
In :func:`base64.b64decode` and :func:`base64.b64decode`, non-alphabet
1296+
characters in the input now result in a :exc:`binascii.Error`.
1297+
You can use :func:`base64.b64decode` with ``validate=False`` and optionally
1298+
the corresponding *altchars* argument to get the old behavior.
1299+
(Contributed by Serhiy Storchaka in :gh:`125346`.)

Lib/base64.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def b64encode(s, altchars=None):
5959
return encoded
6060

6161

62-
def b64decode(s, altchars=None, validate=False):
62+
def b64decode(s, altchars=None, validate=True):
6363
"""Decode the Base64 encoded bytes-like object or ASCII string s.
6464
6565
Optional altchars must be a bytes-like object or ASCII string of length 2
@@ -86,8 +86,8 @@ def b64decode(s, altchars=None, validate=False):
8686
if validate:
8787
s = s.translate(bytes.maketrans(b'+/' + altchars, altchars + b'+/'))
8888
else:
89-
for b in set(b'+/') - set(altchars):
90-
if b in s:
89+
for b in b'+/':
90+
if b not in altchars and b in s:
9191
badchar = b
9292
break
9393
s = s.translate(bytes.maketrans(altchars, b'+/'))

Lib/test/test_base64.py

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def test_b64decode(self):
216216
b"YWI=": b"ab",
217217
b"YWJj": b"abc",
218218
b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE"
219-
b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT"
219+
b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT"
220220
b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==":
221221

222222
b"abcdefghijklmnopqrstuvwxyz"
@@ -286,36 +286,31 @@ def test_b64decode_invalid_chars(self):
286286
(b'!', b''),
287287
(b"YWJj\n", b"abc"),
288288
(b'YWJj\nYWI=', b'abcab'))
289-
funcs = (
290-
base64.b64decode,
291-
base64.standard_b64decode,
292-
base64.urlsafe_b64decode,
293-
)
294289
for bstr, res in tests:
295-
for func in funcs:
296-
with self.subTest(bstr=bstr, func=func):
297-
self.assertEqual(func(bstr), res)
298-
self.assertEqual(func(bstr.decode('ascii')), res)
299-
with self.assertRaises(binascii.Error):
300-
base64.b64decode(bstr, validate=True)
301-
with self.assertRaises(binascii.Error):
302-
base64.b64decode(bstr.decode('ascii'), validate=True)
290+
with self.subTest(bstr=bstr):
291+
for data in bstr, bstr.decode('ascii'):
292+
self.assertEqual(base64.b64decode(data, validate=False), res)
293+
self.assertRaises(binascii.Error, base64.b64decode, data)
294+
self.assertRaises(binascii.Error, base64.standard_b64decode, data)
295+
self.assertRaises(binascii.Error, base64.urlsafe_b64decode, data)
303296

304297
# Normal alphabet characters will be discarded when alternative given
305298
with self.assertWarns(FutureWarning):
306-
self.assertEqual(base64.b64decode(b'++++', altchars=b'-_'),
299+
self.assertEqual(base64.b64decode(b'++++', altchars=b'-_', validate=False),
307300
b'\xfb\xef\xbe')
308301
with self.assertWarns(FutureWarning):
309-
self.assertEqual(base64.b64decode(b'////', altchars=b'-_'),
302+
self.assertEqual(base64.b64decode(b'////', altchars=b'-_', validate=False),
310303
b'\xff\xff\xff')
311-
self.assertEqual(base64.urlsafe_b64decode(b'++++'), b'')
312-
self.assertEqual(base64.urlsafe_b64decode(b'////'), b'')
313304
with self.assertRaises(binascii.Error):
314-
base64.b64decode(b'++++', altchars=b'-_', validate=True)
305+
base64.urlsafe_b64decode(b'++++')
306+
with self.assertRaises(binascii.Error):
307+
base64.urlsafe_b64decode(b'////')
308+
with self.assertRaises(binascii.Error):
309+
base64.b64decode(b'++++', altchars=b'-_')
315310
with self.assertRaises(binascii.Error):
316-
base64.b64decode(b'////', altchars=b'-_', validate=True)
311+
base64.b64decode(b'////', altchars=b'-_')
317312
with self.assertRaises(binascii.Error):
318-
base64.b64decode(b'+/!', altchars=b'-_')
313+
base64.b64decode(b'+/!', altchars=b'-_', validate=False)
319314

320315
def _altchars_strategy():
321316
"""Generate 'altchars' for base64 encoding."""
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In :func:`base64.b64decode`, characters not in the base 64 alphabet now
2+
result in a :exc:`binascii.Error` by default.
3+
If *validate* is false, :exc:`FutureWarning` is now emitted if the ``+`` or
4+
``/`` characters which are not in the alternative alphabet occur in the input.
5+
In :func:`base64.standard_b64decode` and :func:`base64.urlsafe_b64decode`,
6+
non-alphabet characters in the input now result in a :exc:`binascii.Error`.

Misc/NEWS.d/next/Security/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)