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-cli.git
The following commit(s) were added to refs/heads/master by this push:
new 7d77ecce Reject trailing text after the date in Converter.DATE (#435)
7d77ecce is described below
commit 7d77ecce8b11763b7282d6b40dffdb4ce8e85668
Author: farkhalit rida <[email protected]>
AuthorDate: Sat Aug 1 23:56:36 2026 +0530
Reject trailing text after the date in Converter.DATE (#435)
* reject trailing text after the date in Converter.DATE
* Only fall back to English locale when the date fails to parse
Restrict the English retry to when the default-locale parse matches nothing;
a partial match is a trailing-text failure and now throws with the parse
position instead of retrying and reporting a misleading offset.
---
.../java/org/apache/commons/cli/Converter.java | 22 +++++++++++++++++-----
.../org/apache/commons/cli/ConverterTests.java | 18 ++++++++++++++++++
2 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/src/main/java/org/apache/commons/cli/Converter.java
b/src/main/java/org/apache/commons/cli/Converter.java
index fcb9c43b..1faf7817 100644
--- a/src/main/java/org/apache/commons/cli/Converter.java
+++ b/src/main/java/org/apache/commons/cli/Converter.java
@@ -22,6 +22,7 @@ import java.net.URL;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@@ -82,15 +83,26 @@ public interface Converter<T, E extends Exception> {
final SimpleDateFormat format = new SimpleDateFormat(pattern);
// reject out-of-range fields (for example "Feb 30") instead of
silently rolling them over.
format.setLenient(false);
- try {
- return format.parse(s);
- } catch (final java.text.ParseException e) {
+ // SimpleDateFormat.parse(String) stops at the first character it
cannot use and ignores any
+ // trailing text, so "<valid date> garbage" would be accepted. Parse
from an explicit position
+ // and reject the value unless the whole string is consumed.
+ final ParsePosition pos = new ParsePosition(0);
+ Date date = format.parse(s, pos);
+ if (date == null) {
// Date.toString() always emits English month/day names, so fall
back to Locale.ENGLISH
- // when the default locale rejects the documented format.
+ // when the default locale rejects the documented format. Only
retry when the default
+ // locale matched nothing; a partial match is a trailing-text
failure, handled below.
final SimpleDateFormat englishFormat = new
SimpleDateFormat(pattern, Locale.ENGLISH);
englishFormat.setLenient(false);
- return englishFormat.parse(s);
+ pos.setIndex(0);
+ pos.setErrorIndex(-1);
+ date = englishFormat.parse(s, pos);
}
+ if (date == null || pos.getIndex() != s.length()) {
+ final int errorIndex = pos.getErrorIndex() >= 0 ?
pos.getErrorIndex() : pos.getIndex();
+ throw new java.text.ParseException(String.format("Unparseable
date: \"%s\"", s), errorIndex);
+ }
+ return date;
};
/**
diff --git a/src/test/java/org/apache/commons/cli/ConverterTests.java
b/src/test/java/org/apache/commons/cli/ConverterTests.java
index 1f5efad5..64052c41 100644
--- a/src/test/java/org/apache/commons/cli/ConverterTests.java
+++ b/src/test/java/org/apache/commons/cli/ConverterTests.java
@@ -86,6 +86,24 @@ public class ConverterTests {
assertThrows(java.text.ParseException.class, () ->
Converter.DATE.apply("Jun 06 17:48:57 EDT 2002"));
}
+ @Test
+ void testDateRejectsTrailingText() throws Exception {
+ final Date expected = new Date(1023400137000L);
+ final String formatted = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz
yyyy").format(expected);
+ assertThrows(java.text.ParseException.class, () ->
Converter.DATE.apply(formatted + " trailing"));
+ }
+
+ @Test
+ @DefaultLocale(language = "de", country = "DE")
+ void testDateRejectsTrailingTextLocaleDe() throws Exception {
+ // Trailing text must be rejected even when a non-English default
locale parses the date, and
+ // the reported error position should point past the parsed date
rather than at index 0.
+ final Date expected = new Date(1023400137000L);
+ final String formatted = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz
yyyy").format(expected);
+ final java.text.ParseException e =
assertThrows(java.text.ParseException.class, () ->
Converter.DATE.apply(formatted + " trailing"));
+ assertEquals(formatted.length(), e.getErrorOffset());
+ }
+
@Test
@DefaultLocale(language = "de", country = "DE")
void testDateLocaleDe() throws Exception {