diff --git a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java index d05813904d..45adf9f2f6 100644 --- a/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java +++ b/src/main/java/org/apache/commons/text/ExtendedMessageFormat.java @@ -478,12 +478,14 @@ private int readArgumentIndex(final String pattern, final ParsePosition pos) { * @param pos current position. */ private void seekNonWs(final String pattern, final ParsePosition pos) { - int len = 0; final char[] buffer = pattern.toCharArray(); - do { - len = StringMatcherFactory.INSTANCE.splitMatcher().isMatch(buffer, pos.getIndex(), 0, buffer.length); + while (pos.getIndex() < buffer.length) { + final int len = StringMatcherFactory.INSTANCE.splitMatcher().isMatch(buffer, pos.getIndex(), 0, buffer.length); + if (len == 0) { + break; + } pos.setIndex(pos.getIndex() + len); - } while (len > 0 && pos.getIndex() < pattern.length()); + } } /** diff --git a/src/test/java/org/apache/commons/text/ExtendedMessageFormatTest.java b/src/test/java/org/apache/commons/text/ExtendedMessageFormatTest.java index 855207ed53..a4838f6014 100644 --- a/src/test/java/org/apache/commons/text/ExtendedMessageFormatTest.java +++ b/src/test/java/org/apache/commons/text/ExtendedMessageFormatTest.java @@ -236,6 +236,17 @@ void testArgumentIndexTrailingWhitespaceAtEnd() { assertThrowsExactly(IllegalArgumentException.class, () -> new ExtendedMessageFormat("{0 ", new HashMap<>())); } + @Test + void testTruncatedFormatElementWithRegistry() { + // A format element left unterminated at the end of the pattern used to make the + // registry-based constructor seek one past the buffer and throw + // ArrayIndexOutOfBoundsException; it should report the documented + // IllegalArgumentException, as the plain constructor already does. + assertThrowsExactly(IllegalArgumentException.class, () -> new ExtendedMessageFormat("{", new HashMap<>())); + assertThrowsExactly(IllegalArgumentException.class, () -> new ExtendedMessageFormat("{0,", new HashMap<>())); + assertThrowsExactly(IllegalArgumentException.class, () -> new ExtendedMessageFormat("{0}extra{", new HashMap<>())); + } + /** * Test the built in choice format. */