This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new 0ea3250df WordUtils.wrap(wrapLongWords=false, the 2-arg default)
copies the entire remaining string every iteration (f009).
0ea3250df is described below
commit 0ea3250df71c74d68cbf30c7f52c641b63d146ee
Author: Gary Gregory <[email protected]>
AuthorDate: Sat Sep 5 08:00:36 2026 -0400
WordUtils.wrap(wrapLongWords=false, the 2-arg default) copies the entire
remaining string every iteration (f009).
~1 MB of crafted text costs ~45 GB of allocation churn.
---
src/changes/changes.xml | 1 +
src/main/java/org/apache/commons/lang3/text/WordUtils.java | 12 ++++++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ae949589c..e2e06396f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -258,6 +258,7 @@ java.lang.NullPointerException: Cannot invoke
<action type="fix" dev="ggregory" due-to="Gary
Gregory">LocaleUtils static caches no longer grows on invalid input to
LocaleUtils.countriesByLanguage(String) (f007).</action>
<action type="fix" dev="ggregory" due-to="Gary
Gregory">LocaleUtils static caches no longer grows on invalid input to
LocaleUtils.countriesByLanguage(String) (f007).</action>
<action type="fix" dev="ggregory" due-to="Gary
Gregory">ExtendedMessageFormat.applyPattern() is quadratic: full
pattern.toCharArray() per token (f008).</action>
+ <action type="fix" dev="ggregory" due-to="Gary
Gregory">WordUtils.wrap(wrapLongWords=false, the 2-arg default) copies the
entire remaining string every iteration. (f009).</action>
<!-- ADD -->
<action type="add" dev="ggregory" due-to="Gary
Gregory">Add JavaVersion.JAVA_27.</action>
<action type="add" dev="ggregory" due-to="Gary
Gregory">Add SystemUtils.IS_JAVA_27.</action>
diff --git a/src/main/java/org/apache/commons/lang3/text/WordUtils.java
b/src/main/java/org/apache/commons/lang3/text/WordUtils.java
index 23b4f424b..a03a2b8b7 100644
--- a/src/main/java/org/apache/commons/lang3/text/WordUtils.java
+++ b/src/main/java/org/apache/commons/lang3/text/WordUtils.java
@@ -713,12 +713,16 @@ public static String wrap(final String str, int
wrapLength, String newLineStr, f
wrappedLine.append(newLineStr);
offset = wrapAt;
} else {
- // do not wrap really long word, just extend beyond limit
- matcher = patternToWrapOn.matcher(str.substring(offset +
wrapLength));
+ // do not wrap really long word, just extend beyond limit;
+ // match against a region of the original string rather than
copying the entire
+ // unbounded remainder per output line (which is quadratic),
mirroring the
+ // windowed substring used by the main loop above
+ matcher = patternToWrapOn.matcher(str);
+ matcher.region(offset + wrapLength, inputLineLength);
spaceToWrapAt = -1;
if (matcher.find()) {
- spaceToWrapAt = matcher.start() + offset + wrapLength;
- endOfWrapAt = matcher.end() + offset + wrapLength;
+ spaceToWrapAt = matcher.start();
+ endOfWrapAt = matcher.end();
}
if (spaceToWrapAt >= 0) {