Skip to content

Commit cbe9bb7

Browse files
committed
fix performance regression in striptags
The regex implementation was removed in #413 with no clear benchmarks and replaced by a version containing quadratic string manipulation that does not scale. Fixing the implementation by appending sub-strings to a list and by doing a single loop over the value. fixes #521
1 parent b2e4d9c commit cbe9bb7

2 files changed

Lines changed: 23 additions & 17 deletions

File tree

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Unreleased
55

66
- Drop support for Python 3.9.
77
- Remove previously deprecated code.
8+
- Fix performance issue with ``striptags``. :issue:`521`
89

910

1011
Version 3.0.3

src/markupsafe/__init__.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -204,24 +204,29 @@ def striptags(self, /) -> str:
204204
'Main » About'
205205
"""
206206
value = str(self)
207-
208-
# Look for comments then tags separately. Otherwise, a comment that
209-
# contains a tag would end early, leaving some of the comment behind.
210-
211-
# keep finding comment start marks
212-
while (start := value.find("<!--")) != -1:
213-
# find a comment end mark beyond the start, otherwise stop
214-
if (end := value.find("-->", start)) == -1:
215-
break
216-
217-
value = f"{value[:start]}{value[end + 3 :]}"
218-
219-
# remove tags using the same method
220-
while (start := value.find("<")) != -1:
221-
if (end := value.find(">", start)) == -1:
207+
parts = []
208+
prev = 0
209+
while True:
210+
start = value.find("<", prev)
211+
if start == -1:
222212
break
223-
224-
value = f"{value[:start]}{value[end + 1 :]}"
213+
if value[start : start + 4] == "<!--":
214+
# comment
215+
end = value.find("-->", start)
216+
if end == -1:
217+
break
218+
parts.append(value[prev:start])
219+
prev = end + 3
220+
else:
221+
# tag
222+
end = value.find(">", start)
223+
if end == -1:
224+
break
225+
parts.append(value[prev:start])
226+
prev = end + 1
227+
if prev > 0:
228+
parts.append(value[prev:])
229+
value = "".join(parts)
225230

226231
# collapse spaces
227232
value = " ".join(value.split())

0 commit comments

Comments
 (0)