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. 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.