]> granicus.if.org Git - icu/commitdiff
ICU-21802 Fix error where strict date parsing could succeed on certain malformed...
authorRich Gillam <62772518+richgillam@users.noreply.github.com>
Fri, 25 Feb 2022 02:53:02 +0000 (18:53 -0800)
committerRich Gillam <62772518+richgillam@users.noreply.github.com>
Mon, 28 Feb 2022 20:01:44 +0000 (12:01 -0800)
icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/test/cintltst/cdattst.c
icu4j/main/classes/core/src/com/ibm/icu/text/SimpleDateFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/DateFormatTest.java

index 91748d82f9fd648e1ec28923495d92a213df5640..c1e943a0949da20b68adcdc60a2e6cede0c07e6c 100644 (file)
@@ -3792,6 +3792,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
         src = &text;
     }
     parseInt(*src, number, pos, allowNegative,currentNumberFormat);
+    if (!isLenient() && pos.getIndex() < start + count) {
+        return -start;
+    }
     if (pos.getIndex() != parseStart) {
         int32_t val = number.getLong();
 
index 00b2d6a01a1d2661b1406e895550e7bc91de8ffc..2c5d51c64b24a7d1ecf08c4bd5deb186b37985b0 100644 (file)
@@ -45,6 +45,7 @@ static void TestFormatForFields(void);
 static void TestForceGannenNumbering(void);
 static void TestMapDateToCalFields(void);
 static void TestNarrowQuarters(void);
+static void TestExtraneousCharacters(void);
 
 void addDateForTest(TestNode** root);
 
@@ -67,6 +68,7 @@ void addDateForTest(TestNode** root)
     TESTCASE(TestForceGannenNumbering);
     TESTCASE(TestMapDateToCalFields);
     TESTCASE(TestNarrowQuarters);
+    TESTCASE(TestExtraneousCharacters);
 }
 /* Testing the DateFormat API */
 static void TestDateFormat()
@@ -2017,4 +2019,24 @@ static void TestNarrowQuarters(void) {
     }
 }
 
+static void TestExtraneousCharacters(void) {
+    // regression test for ICU-21802
+    UErrorCode err = U_ZERO_ERROR;
+    UCalendar* cal = ucal_open(u"UTC", -1, "en_US", UCAL_GREGORIAN, &err);
+    UDateFormat* df = udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", u"UTC", -1, u"yyyyMMdd", -1, &err);
+    
+    if (assertSuccess("Failed to create date formatter and calendar", &err)) {
+        udat_setLenient(df, false);
+
+        udat_parseCalendar(df, cal, u"2021", -1, NULL, &err);
+        assertTrue("Success parsing '2021'", err == U_PARSE_ERROR);
+        
+        err = U_ZERO_ERROR;
+        udat_parseCalendar(df, cal, u"2021-", -1, NULL, &err);
+        assertTrue("Success parsing '2021-'", err == U_PARSE_ERROR);
+    }
+    udat_close(df);
+    ucal_close(cal);
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 910f96afa45a190671eca9479e018a4d265f3ac6..1f3d25f0c15838db9e5199794ceb175531acfdc1 100644 (file)
@@ -3787,6 +3787,9 @@ public class SimpleDateFormat extends DateFormat {
                 } else {
                     number = parseInt(text, pos, allowNegative,currentNumberFormat);
                 }
+                if (!isLenient() && pos.getIndex() < start + count) {
+                    return -start;
+                }
                 if (number != null) {
                     if (patternCharIndex != DateFormat.RELATED_YEAR) {
                         cal.set(field, number.intValue());
index 3f25d642f010f5b5917ef9e502a3baf44d8d32af..27e42fa9dd769e1500f6547bd653b09497c03800 100644 (file)
@@ -5610,4 +5610,20 @@ public class DateFormatTest extends TestFmwk {
             }
         }
     }
+
+    @Test
+    public void testExtraneousCharacters() {
+        // regression test for ICU-21802
+        Calendar cal = Calendar.getInstance();
+        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd", ULocale.US);
+        df.setLenient(false);
+
+        ParsePosition pos = new ParsePosition(0);
+        df.parse("2021", cal, pos);
+        assertTrue("Success parsing '2021'", pos.getIndex() == 0);
+
+        pos.setIndex(0);
+        df.parse("2021-", cal, pos);
+        assertTrue("Success parsing '2021-'", pos.getIndex() == 0);
+    }
 }