Skip to content

Commit 693adf3

Browse files
committed
ICU-20558 Fix regression in DateTimePatternGenerator
This fixes a regression introduced by commit b12a927 for issue ICU-13778. The above commit improved the error checking in the DateTimePatternGenerator class, adding checks for errors/failures where there previously was none at all. This was done in order to catch catastrophic errors like out-of-memory (OOM), and properly report them to the caller, rather than ignoring/hiding these errors. However, in doing so it exposed a case where the code was depending on ignoring errors in order to fall-back to the Gregorian calendar when the default ICU locale is set to root. This restores the previous behavior, by allowing the error of U_MISSING_RESOURCE_ERROR to fall-though and continue without reporting back an error to the caller. Note: This regression was technically introduced in ICU 63, and also effects ICU 64 as well.
1 parent 711e7e0 commit 693adf3

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

icu4c/source/i18n/dtptngen.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ void
787787
DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& destination, UErrorCode& err) {
788788
destination.clear().append(DT_DateTimeGregorianTag, -1, err); // initial default
789789
if ( U_SUCCESS(err) ) {
790+
UErrorCode localStatus = U_ZERO_ERROR;
790791
char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
791792
// obtain a locale that always has the calendar key value that should be used
792793
ures_getFunctionalEquivalent(
@@ -798,8 +799,7 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString&
798799
locale.getName(),
799800
nullptr,
800801
FALSE,
801-
&err);
802-
if (U_FAILURE(err)) { return; }
802+
&localStatus);
803803
localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
804804
// now get the calendar key value from that locale
805805
char calendarType[ULOC_KEYWORDS_CAPACITY];
@@ -808,13 +808,17 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString&
808808
"calendar",
809809
calendarType,
810810
ULOC_KEYWORDS_CAPACITY,
811-
&err);
812-
if (U_FAILURE(err)) { return; }
811+
&localStatus);
812+
// If the input locale was invalid, don't fail with missing resource error, instead
813+
// continue with default of Gregorian.
814+
if (U_FAILURE(localStatus) && localStatus != U_MISSING_RESOURCE_ERROR) {
815+
err = localStatus;
816+
return;
817+
}
813818
if (calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
814819
destination.clear().append(calendarType, -1, err);
815820
if (U_FAILURE(err)) { return; }
816821
}
817-
err = U_ZERO_ERROR;
818822
}
819823
}
820824

icu4c/source/test/intltest/dtptngts.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e
4141
TESTCASE(5, testSkeletonsWithDayPeriods);
4242
TESTCASE(6, testGetFieldDisplayNames);
4343
TESTCASE(7, testJjMapping);
44+
TESTCASE(8, testFallbackWithDefaultRootLocale);
4445
default: name = ""; break;
4546
}
4647
}
@@ -1341,4 +1342,31 @@ void IntlTestDateTimePatternGeneratorAPI::testJjMapping() {
13411342
}
13421343
}
13431344

1345+
void IntlTestDateTimePatternGeneratorAPI::testFallbackWithDefaultRootLocale() {
1346+
UErrorCode status = U_ZERO_ERROR;
1347+
char original[ULOC_FULLNAME_CAPACITY];
1348+
1349+
uprv_strcpy(original, uloc_getDefault());
1350+
uloc_setDefault("root", &status);
1351+
if (U_FAILURE(status)) {
1352+
errln("ERROR: Failed to change the default locale to root! Default is: %s\n", uloc_getDefault());
1353+
}
1354+
1355+
DateTimePatternGenerator* dtpg = icu::DateTimePatternGenerator::createInstance("abcdedf", status);
1356+
1357+
if (U_FAILURE(status)) {
1358+
errln("ERROR: expected createInstance with invalid locale to succeed. Status: %s", u_errorName(status));
1359+
}
1360+
if (status != U_USING_DEFAULT_WARNING) {
1361+
errln("ERROR: expected createInstance to return U_USING_DEFAULT_WARNING for invalid locale and default root locale. Status: %s", u_errorName(status));
1362+
}
1363+
1364+
delete dtpg;
1365+
1366+
uloc_setDefault(original, &status);
1367+
if (U_FAILURE(status)) {
1368+
errln("ERROR: Failed to change the default locale back to %s\n", original);
1369+
}
1370+
}
1371+
13441372
#endif /* #if !UCONFIG_NO_FORMATTING */

icu4c/source/test/intltest/dtptngts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class IntlTestDateTimePatternGeneratorAPI : public IntlTest {
3333
void testSkeletonsWithDayPeriods();
3434
void testGetFieldDisplayNames();
3535
void testJjMapping();
36+
void testFallbackWithDefaultRootLocale();
3637
};
3738

3839
#endif /* #if !UCONFIG_NO_FORMATTING */

0 commit comments

Comments
 (0)