Skip to content

Commit e873272

Browse files
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.
1 parent 502ca0d commit e873272

File tree

2 files changed

+7
-1
lines changed

2 files changed

+7
-1
lines changed

Lib/email/_header_value_parser.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3081,13 +3081,17 @@ def _fold_mime_parameters(part, lines, maxlen, encoding):
30813081
# the RFC standard width.
30823082
maxlen = 78
30833083
splitpoint = maxchars = maxlen - chrome_len - 2
3084-
while True:
3084+
splitpoint = max(1, splitpoint) # Ensure splitpoint is always at least 1
3085+
while splitpoint > 1:
30853086
partial = value[:splitpoint]
30863087
encoded_value = urllib.parse.quote(
30873088
partial, safe='', errors=error_handler)
30883089
if len(encoded_value) <= maxchars:
30893090
break
30903091
splitpoint -= 1
3092+
# If we still can't fit, force a minimal split
3093+
if splitpoint <= 1:
3094+
splitpoint = 1
30913095
lines.append(" {}*{}*={}{}".format(
30923096
name, section, extra_chrome, encoded_value))
30933097
extra_chrome = ''

Lib/email/header.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,8 @@ def _append_chunk(self, fws, string):
527527
continue
528528
break
529529
else:
530+
# No suitable split point found. Handle the case where we have
531+
# an extremely long string that can't be split.
530532
fws, part = self._current_line.pop()
531533
if self._current_line._initial_size > 0:
532534
# There will be a header, so leave it on a line by itself.

0 commit comments

Comments
 (0)