[Python-checkins] [3.6] bpo-34164: Fix handling of incorrect padding in base64.b32decode(). (GH-8351) (GH-8436)

Serhiy Storchaka webhook-mailer at python.org
Tue Jul 24 08:07:02 EDT 2018


https://github.com/python/cpython/commit/113f86e7487e9312a2494667b088854ac942ab00
commit: 113f86e7487e9312a2494667b088854ac942ab00
branch: 3.6
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-07-24T15:06:59+03:00
summary:

[3.6] bpo-34164: Fix handling of incorrect padding in base64.b32decode(). (GH-8351) (GH-8436)

Now base64.Error is always raised instead of UnboundLocalError or
OverflowError.
(cherry picked from commit ac0b3c2f4d86fc056b833a4e6b9a380741244a63)

Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>

files:
A Misc/NEWS.d/next/Library/2018-07-20-18-06-00.bpo-34164.fNfT-q.rst
M Lib/base64.py
M Lib/test/test_base64.py

diff --git a/Lib/base64.py b/Lib/base64.py
index eb8f258a2d19..2be9c395a966 100755
--- a/Lib/base64.py
+++ b/Lib/base64.py
@@ -231,23 +231,16 @@ def b32decode(s, casefold=False, map01=None):
             raise binascii.Error('Non-base32 digit found') from None
         decoded += acc.to_bytes(5, 'big')
     # Process the last, partial quanta
-    if padchars:
+    if l % 8 or padchars not in {0, 1, 3, 4, 6}:
+        raise binascii.Error('Incorrect padding')
+    if padchars and decoded:
         acc <<= 5 * padchars
         last = acc.to_bytes(5, 'big')
-        if padchars == 1:
-            decoded[-5:] = last[:-1]
-        elif padchars == 3:
-            decoded[-5:] = last[:-2]
-        elif padchars == 4:
-            decoded[-5:] = last[:-3]
-        elif padchars == 6:
-            decoded[-5:] = last[:-4]
-        else:
-            raise binascii.Error('Incorrect padding')
+        leftover = (43 - 5 * padchars) // 8  # 1: 4, 3: 3, 4: 2, 6: 1
+        decoded[-5:] = last[:leftover]
     return bytes(decoded)
 
 
-
 # RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
 # lowercase.  The RFC also recommends against accepting input case
 # insensitively.
diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py
index 47547396b8cb..2a4cc2acad24 100644
--- a/Lib/test/test_base64.py
+++ b/Lib/test/test_base64.py
@@ -343,11 +343,20 @@ def test_b32decode_casefold(self):
             self.assertRaises(binascii.Error, base64.b32decode, data_str)
 
     def test_b32decode_error(self):
-        for data in [b'abc', b'ABCDEF==', b'==ABCDEF']:
-            with self.assertRaises(binascii.Error):
-                base64.b32decode(data)
-            with self.assertRaises(binascii.Error):
-                base64.b32decode(data.decode('ascii'))
+        tests = [b'abc', b'ABCDEF==', b'==ABCDEF']
+        prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
+        for i in range(0, 17):
+            if i:
+                tests.append(b'='*i)
+            for prefix in prefixes:
+                if len(prefix) + i != 8:
+                    tests.append(prefix + b'='*i)
+        for data in tests:
+            with self.subTest(data=data):
+                with self.assertRaises(binascii.Error):
+                    base64.b32decode(data)
+                with self.assertRaises(binascii.Error):
+                    base64.b32decode(data.decode('ascii'))
 
     def test_b16encode(self):
         eq = self.assertEqual
diff --git a/Misc/NEWS.d/next/Library/2018-07-20-18-06-00.bpo-34164.fNfT-q.rst b/Misc/NEWS.d/next/Library/2018-07-20-18-06-00.bpo-34164.fNfT-q.rst
new file mode 100644
index 000000000000..99bf169308c0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-07-20-18-06-00.bpo-34164.fNfT-q.rst
@@ -0,0 +1,2 @@
+:func:`base64.b32decode` could raise UnboundLocalError or OverflowError for
+incorrect padding.  Now it always raises :exc:`base64.Error` in these cases.



More information about the Python-checkins mailing list