From e8732721554697e392dc59ad1bb0edb10b202058 Mon Sep 17 00:00:00 2001 From: Chenyang Li Date: Thu, 28 Aug 2025 12:12:21 -0400 Subject: [PATCH 1/2] Fix infinite loop in email.message.EmailMessage.as_string() with long parameter keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The infinite loop occurred in _fold_mime_parameters() when processing MIME parameters with very long keys (≥64 characters) during RFC 2231 encoding. The issue was in two locations: 1. In email._header_value_parser._fold_mime_parameters(): - Replace infinite while True: loop with while splitpoint > 1: - Ensure splitpoint is always at least 1 to prevent getting stuck - Add fallback logic to force minimal splits when values cannot fit 2. In email.header._ValueFormatter._append_chunk(): - Add safety check for extremely long strings that cannot be split - Force line breaks when no suitable split points are found - Prevent infinite loops in header folding for edge cases This fixes GitHub issue #138223 where add_attachment() with long parameter keys would cause as_string() to hang indefinitely during MIME parameter folding and header processing. --- Lib/email/_header_value_parser.py | 6 +++++- Lib/email/header.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 91243378dc0441..5ad7259b505677 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -3081,13 +3081,17 @@ def _fold_mime_parameters(part, lines, maxlen, encoding): # the RFC standard width. maxlen = 78 splitpoint = maxchars = maxlen - chrome_len - 2 - while True: + splitpoint = max(1, splitpoint) # Ensure splitpoint is always at least 1 + while splitpoint > 1: partial = value[:splitpoint] encoded_value = urllib.parse.quote( partial, safe='', errors=error_handler) if len(encoded_value) <= maxchars: break splitpoint -= 1 + # If we still can't fit, force a minimal split + if splitpoint <= 1: + splitpoint = 1 lines.append(" {}*{}*={}{}".format( name, section, extra_chrome, encoded_value)) extra_chrome = '' diff --git a/Lib/email/header.py b/Lib/email/header.py index a0aadb97ca68c8..9d1906dad37633 100644 --- a/Lib/email/header.py +++ b/Lib/email/header.py @@ -527,6 +527,8 @@ def _append_chunk(self, fws, string): continue break else: + # No suitable split point found. Handle the case where we have + # an extremely long string that can't be split. fws, part = self._current_line.pop() if self._current_line._initial_size > 0: # There will be a header, so leave it on a line by itself. From c8fc88e22a3f3171e0b0b58b300a4f2488784009 Mon Sep 17 00:00:00 2001 From: Chenyang Li Date: Thu, 28 Aug 2025 12:23:17 -0400 Subject: [PATCH 2/2] Fix infinite loop in email.message.EmailMessage.as_string() with long parameter keys The infinite loop occurred in _fold_mime_parameters() when processing MIME parameters with very long keys (64 characters) during RFC 2231 encoding. The issue was in two locations: 1. In email._header_value_parser._fold_mime_parameters(): - Replace infinite 'while True:' loop with 'while splitpoint > 1:' - Ensure splitpoint is always at least 1 to prevent getting stuck - Add fallback logic to force minimal splits when values cannot fit 2. In email.header._ValueFormatter._append_chunk(): - Add safety check for extremely long strings that cannot be split - Force line breaks when no suitable split points are found - Prevent infinite loops in header folding for edge cases This fixes GitHub issue #138223 where add_attachment() with long parameter keys would cause as_string() to hang indefinitely during MIME parameter folding and header processing. --- .../2025-01-27-12-00-00.gh-issue-138223.email-infinite-loop.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-01-27-12-00-00.gh-issue-138223.email-infinite-loop.rst diff --git a/Misc/NEWS.d/next/Library/2025-01-27-12-00-00.gh-issue-138223.email-infinite-loop.rst b/Misc/NEWS.d/next/Library/2025-01-27-12-00-00.gh-issue-138223.email-infinite-loop.rst new file mode 100644 index 00000000000000..1dc334c2cbf242 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-27-12-00-00.gh-issue-138223.email-infinite-loop.rst @@ -0,0 +1 @@ +Fix infinite loop in email.message.EmailMessage.as_string() when add_attachment() is called with very long parameter keys.