Issue #4770: Restrict binascii module to accept only bytes (as specified).
And fix the email package to encode to ASCII instead of ``raw-unicode-escape`` before ASCII-to-binary decoding.
diff --git a/Lib/email/base64mime.py b/Lib/email/base64mime.py
index 6cbfdf6..f3bbac1 100644
--- a/Lib/email/base64mime.py
+++ b/Lib/email/base64mime.py
@@ -74,12 +74,12 @@
def body_encode(s, maxlinelen=76, eol=NL):
- """Encode a string with base64.
+ r"""Encode a string with base64.
Each line will be wrapped at, at most, maxlinelen characters (defaults to
76 characters).
- Each line of encoded text will end with eol, which defaults to "\\n". Set
+ Each line of encoded text will end with eol, which defaults to "\n". Set
this to "\r\n" if you will be using the result of this function directly
in an email.
"""
diff --git a/Lib/email/message.py b/Lib/email/message.py
index 27a577d..520d63d 100644
--- a/Lib/email/message.py
+++ b/Lib/email/message.py
@@ -198,17 +198,19 @@
return None
cte = self.get('content-transfer-encoding', '').lower()
if cte == 'quoted-printable':
+ if isinstance(payload, str):
+ payload = payload.encode('ascii')
return utils._qdecode(payload)
elif cte == 'base64':
try:
if isinstance(payload, str):
- payload = payload.encode('raw-unicode-escape')
+ payload = payload.encode('ascii')
return base64.b64decode(payload)
except binascii.Error:
# Incorrect padding
pass
elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'):
- in_file = BytesIO(payload.encode('raw-unicode-escape'))
+ in_file = BytesIO(payload.encode('ascii'))
out_file = BytesIO()
try:
uu.decode(in_file, out_file, quiet=True)
diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py
index 3c6d88f..1e9e888 100644
--- a/Lib/test/test_binascii.py
+++ b/Lib/test/test_binascii.py
@@ -55,7 +55,7 @@
"{!r} != {!r}".format(fb, fa, res, raw))
self.assertIsInstance(res, bytes)
self.assertIsInstance(a, bytes)
- self.assertLess(max(c for c in a), 128)
+ self.assertLess(max(a), 128)
self.assertIsInstance(binascii.crc_hqx(raw, 0), int)
self.assertIsInstance(binascii.crc32(raw), int)
@@ -167,7 +167,7 @@
def test_qp(self):
# A test for SF bug 534347 (segfaults without the proper fix)
try:
- binascii.a2b_qp("", **{1:1})
+ binascii.a2b_qp(b"", **{1:1})
except TypeError:
pass
else:
@@ -179,12 +179,10 @@
self.assertEqual(binascii.a2b_qp(b"=00\r\n=00"), b"\x00\r\n\x00")
self.assertEqual(
binascii.b2a_qp(b"\xff\r\n\xff\n\xff"),
- b"=FF\r\n=FF\r\n=FF"
- )
+ b"=FF\r\n=FF\r\n=FF")
self.assertEqual(
binascii.b2a_qp(b"0"*75+b"\xff\r\n\xff\r\n\xff"),
- b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF"
- )
+ b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF")
self.assertEqual(binascii.b2a_qp(b'\0\n'), b'=00\n')
self.assertEqual(binascii.b2a_qp(b'\0\n', quotetabs=True), b'=00\n')
@@ -210,13 +208,15 @@
except Exception as err:
self.fail("{}({!r}) raises {!r}".format(func, empty, err))
- def test_no_binary_strings(self):
- # b2a_ must not accept strings
- for f in (binascii.b2a_uu, binascii.b2a_base64,
- binascii.b2a_hqx, binascii.b2a_qp,
- binascii.hexlify, binascii.rlecode_hqx,
- binascii.crc_hqx, binascii.crc32):
- self.assertRaises(TypeError, f, "test")
+ def test_unicode_strings(self):
+ # Unicode strings are not accepted.
+ for func in all_functions:
+ try:
+ self.assertRaises(TypeError, getattr(binascii, func), "test")
+ except Exception as err:
+ self.fail('{}("test") raises {!r}'.format(func, err))
+ # crc_hqx needs 2 arguments
+ self.assertRaises(TypeError, binascii.crc_hqx, "test", 0)
class ArrayBinASCIITest(BinASCIITest):
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index b923f45..6ca35ca 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -213,6 +213,7 @@
expected = '%x' % expected
if len(expected) & 1:
expected = "0" + expected
+ expected = expected.encode('ascii')
expected = unhexlify(expected)
expected = (b"\x00" * (self.bytesize - len(expected)) +
expected)