Skip to content

Commit d19f738

Browse files
committed
gh-158979: Fix infinite loop in textwrap when indent is wider than width
_handle_long_word() left an empty chunk on the stack after using up a one-character chunk, and _wrap_chunks() could not consume it when the indent was wider than the width.
1 parent 9d22a53 commit d19f738

3 files changed

Lines changed: 22 additions & 1 deletion

File tree

‎Lib/test/test_textwrap.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,18 @@ def test_break_long(self):
615615
'word,',
616616
'anyways?'])
617617

618+
def test_indent_wider_than_width(self):
619+
# These used to loop forever or to add an extra last line when the
620+
# indent was not narrower than the width.
621+
self.check_wrap(' x', 1, [' x'], initial_indent=' ')
622+
self.check_wrap(' ', 5, [], initial_indent=' ')
623+
self.check_wrap('abc', 2, ['ab', ' c'],
624+
subsequent_indent=' ', drop_whitespace=False)
625+
self.check_wrap('x', 1, [' x'],
626+
initial_indent=' ', drop_whitespace=False)
627+
self.check_wrap('abcdef', 3, ['abc', ' d', ' e', ' f'],
628+
subsequent_indent=' ', drop_whitespace=False)
629+
618630
def test_nobreak_long(self):
619631
# Test with break_long_words disabled
620632
self.wrapper.break_long_words = 0

‎Lib/textwrap.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,12 @@ def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
221221
if hyphen > 0 and any(c != '-' for c in chunk[:hyphen]):
222222
end = hyphen + 1
223223
cur_line.append(chunk[:end])
224-
reversed_chunks[-1] = chunk[end:]
224+
if end < len(chunk):
225+
reversed_chunks[-1] = chunk[end:]
226+
else:
227+
# The whole chunk fit, which happens only when the indent is
228+
# not narrower than the width. Don't leave an empty chunk.
229+
reversed_chunks.pop()
225230

226231
# Otherwise, we have to preserve the long word intact. Only add
227232
# it to the current line if there's nothing already there --
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix an infinite loop in :func:`textwrap.wrap` and :func:`textwrap.fill` when
2+
the indent is wider than *width* and the text starts with whitespace, or
3+
*drop_whitespace* is false. They also no longer add an empty or indent-only
4+
last line in some cases where the indent is not narrower than *width*.

0 commit comments

Comments
 (0)