From aa79707262f893428665ef45b5e879129abca4aa Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 4 Jun 2019 14:00:47 -0400 Subject: [PATCH] bpo-30835: email: Fix AttributeError when parsing invalid CTE (GH-13598) * bpo-30835: email: Fix AttributeError when parsing invalid Content-Transfer-Encoding Parsing an email containing a multipart Content-Type, along with a Content-Transfer-Encoding containing an invalid (non-ASCII-decodable) byte will fail. email.feedparser.FeedParser._parsegen() gets the header and attempts to convert it to lowercase before comparing it with the accepted encodings, but as the header contains an invalid byte, it's returned as a Header object rather than a str. Cast the Content-Transfer-Encoding header to a str to avoid this. Found using the AFL fuzzer. Reported-by: Daniel Axtens Signed-off-by: Andrew Donnellan * Add email and NEWS entry for the bugfix. --- Lib/email/feedparser.py | 2 +- Lib/test/test_email/test_email.py | 9 +++++++++ .../Library/2019-05-27-15-29-46.bpo-30835.3FoaWH.rst | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2019-05-27-15-29-46.bpo-30835.3FoaWH.rst diff --git a/Lib/email/feedparser.py b/Lib/email/feedparser.py index 7c07ca86457..97d3f5144d6 100644 --- a/Lib/email/feedparser.py +++ b/Lib/email/feedparser.py @@ -320,7 +320,7 @@ class FeedParser: self._cur.set_payload(EMPTYSTRING.join(lines)) return # Make sure a valid content type was specified per RFC 2045:6.4. - if (self._cur.get('content-transfer-encoding', '8bit').lower() + if (str(self._cur.get('content-transfer-encoding', '8bit')).lower() not in ('7bit', '8bit', 'binary')): defect = errors.InvalidMultipartContentTransferEncodingDefect() self.policy.handle_defect(self._cur, defect) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index dfb3be84384..c29cc56203b 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -1466,6 +1466,15 @@ Blah blah blah g.flatten(msg) self.assertEqual(b.getvalue(), source + b'>From R\xc3\xb6lli\n') + def test_mutltipart_with_bad_bytes_in_cte(self): + # bpo30835 + source = textwrap.dedent("""\ + From: aperson@example.com + Content-Type: multipart/mixed; boundary="1" + Content-Transfer-Encoding: \xc8 + """).encode('utf-8') + msg = email.message_from_bytes(source) + # Test the basic MIMEAudio class class TestMIMEAudio(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-05-27-15-29-46.bpo-30835.3FoaWH.rst b/Misc/NEWS.d/next/Library/2019-05-27-15-29-46.bpo-30835.3FoaWH.rst new file mode 100644 index 00000000000..019321d6f1d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-27-15-29-46.bpo-30835.3FoaWH.rst @@ -0,0 +1,3 @@ +Fixed a bug in email parsing where a message with invalid bytes in +content-transfer-encoding of a multipart message can cause an AttributeError. +Patch by Andrew Donnellan.