Skip to content

Commit ac0b3c2

Browse files
bpo-34164: Fix handling of incorrect padding in base64.b32decode(). (GH-8351)
Now base64.Error is always raised instead of UnboundLocalError or OverflowError.
1 parent 02ec92f commit ac0b3c2

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

Lib/base64.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,23 +231,16 @@ def b32decode(s, casefold=False, map01=None):
231231
raise binascii.Error('Non-base32 digit found') from None
232232
decoded += acc.to_bytes(5, 'big')
233233
# Process the last, partial quanta
234-
if padchars:
234+
if l % 8 or padchars not in {0, 1, 3, 4, 6}:
235+
raise binascii.Error('Incorrect padding')
236+
if padchars and decoded:
235237
acc <<= 5 * padchars
236238
last = acc.to_bytes(5, 'big')
237-
if padchars == 1:
238-
decoded[-5:] = last[:-1]
239-
elif padchars == 3:
240-
decoded[-5:] = last[:-2]
241-
elif padchars == 4:
242-
decoded[-5:] = last[:-3]
243-
elif padchars == 6:
244-
decoded[-5:] = last[:-4]
245-
else:
246-
raise binascii.Error('Incorrect padding')
239+
leftover = (43 - 5 * padchars) // 8 # 1: 4, 3: 3, 4: 2, 6: 1
240+
decoded[-5:] = last[:leftover]
247241
return bytes(decoded)
248242

249243

250-
251244
# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
252245
# lowercase. The RFC also recommends against accepting input case
253246
# insensitively.

Lib/test/test_base64.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,20 @@ def test_b32decode_casefold(self):
343343
self.assertRaises(binascii.Error, base64.b32decode, data_str)
344344

345345
def test_b32decode_error(self):
346-
for data in [b'abc', b'ABCDEF==', b'==ABCDEF']:
347-
with self.assertRaises(binascii.Error):
348-
base64.b32decode(data)
349-
with self.assertRaises(binascii.Error):
350-
base64.b32decode(data.decode('ascii'))
346+
tests = [b'abc', b'ABCDEF==', b'==ABCDEF']
347+
prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
348+
for i in range(0, 17):
349+
if i:
350+
tests.append(b'='*i)
351+
for prefix in prefixes:
352+
if len(prefix) + i != 8:
353+
tests.append(prefix + b'='*i)
354+
for data in tests:
355+
with self.subTest(data=data):
356+
with self.assertRaises(binascii.Error):
357+
base64.b32decode(data)
358+
with self.assertRaises(binascii.Error):
359+
base64.b32decode(data.decode('ascii'))
351360

352361
def test_b16encode(self):
353362
eq = self.assertEqual
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`base64.b32decode` could raise UnboundLocalError or OverflowError for
2+
incorrect padding. Now it always raises :exc:`base64.Error` in these cases.

0 commit comments

Comments
 (0)