diff --git a/src/main/java/org/apache/commons/cli/help/TextHelpAppendable.java b/src/main/java/org/apache/commons/cli/help/TextHelpAppendable.java index 14c90c7c2..2b053106c 100644 --- a/src/main/java/org/apache/commons/cli/help/TextHelpAppendable.java +++ b/src/main/java/org/apache/commons/cli/help/TextHelpAppendable.java @@ -76,19 +76,22 @@ public static int indexOfWrap(final CharSequence text, final int width, final in if (width < 1) { throw new IllegalArgumentException("Width must be greater than 0"); } + // width can be Integer.MAX_VALUE (TextStyle.UNSET_MAX_WIDTH), so keep the wrap boundary in a long; + // startPos + width as an int overflows to a negative value and yields a negative wrap index. + final long end = (long) startPos + width; // handle case of width > text. // the line ends before the max wrap pos or a new line char found - int limit = Math.min(startPos + width, text.length()); + int limit = (int) Math.min(end, text.length()); for (int idx = startPos; idx < limit; idx++) { if (BREAK_CHAR_SET.contains(text.charAt(idx))) { return idx; } } - if (startPos + width >= text.length()) { + if (end >= text.length()) { return text.length(); } - limit = Math.min(startPos + width, text.length() - 1); + limit = (int) Math.min(end, text.length() - 1); int pos; // look for the last whitespace character before limit for (pos = limit; pos >= startPos; --pos) { diff --git a/src/test/java/org/apache/commons/cli/help/TextHelpAppendableTest.java b/src/test/java/org/apache/commons/cli/help/TextHelpAppendableTest.java index 9c58427d5..182cf50fc 100644 --- a/src/test/java/org/apache/commons/cli/help/TextHelpAppendableTest.java +++ b/src/test/java/org/apache/commons/cli/help/TextHelpAppendableTest.java @@ -280,6 +280,10 @@ void testindexOfWrapPos() { assertThrows(IllegalArgumentException.class, () -> TextHelpAppendable.indexOfWrap("", 0, 0)); assertEquals(3, TextHelpAppendable.indexOfWrap("Hello", 4, 0)); + + // startPos + width must not overflow when width is TextStyle.UNSET_MAX_WIDTH + assertEquals(30, TextHelpAppendable.indexOfWrap(testString, TextStyle.UNSET_MAX_WIDTH, 0), "did not find break character with unbounded width"); + assertEquals(testString.length(), TextHelpAppendable.indexOfWrap(testString, TextStyle.UNSET_MAX_WIDTH, 31), "overflow produced a negative wrap index"); } @ParameterizedTest