From 7bef50e71d6ae7a58c5547092feb110ec71810ab Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Fri, 15 Dec 2023 13:06:42 -0800 Subject: [PATCH] ICU-22609 Fix nulldef w/ bogus locale in DateFormat::create* --- icu4c/source/i18n/smpdtfmt.cpp | 7 ++++--- icu4c/source/test/cintltst/cdattst.c | 15 +++++++++++++++ icu4c/source/test/intltest/dtfmttst.cpp | 9 +++++++++ icu4c/source/test/intltest/dtfmttst.h | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index d767babe7fe..1c7606da5ca 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -728,16 +728,17 @@ void SimpleDateFormat::construct(EStyle timeStyle, if (locale.getKeywordValue("rg", nullptr, 0, dummyErr1) > 0 || locale.getKeywordValue("hours", nullptr, 0, dummyErr2) > 0) { hasRgOrHcSubtag = true; } - + const char* baseLocID = locale.getBaseName(); - if (baseLocID[0]!=0 && uprv_strcmp(baseLocID,"und")!=0) { + if (baseLocID != nullptr && uprv_strcmp(baseLocID,"und")!=0) { UErrorCode useStatus = U_ZERO_ERROR; Locale baseLoc(baseLocID); Locale validLoc(getLocale(ULOC_VALID_LOCALE, useStatus)); if (hasRgOrHcSubtag || (U_SUCCESS(useStatus) && validLoc!=baseLoc)) { bool useDTPG = hasRgOrHcSubtag; const char* baseReg = baseLoc.getCountry(); // empty string if no region - if ((baseReg[0]!=0 && uprv_strncmp(baseReg,validLoc.getCountry(),ULOC_COUNTRY_CAPACITY)!=0) + if ((baseReg != nullptr && baseReg[0] != 0 && + uprv_strncmp(baseReg,validLoc.getCountry(),ULOC_COUNTRY_CAPACITY)!=0) || uprv_strncmp(baseLoc.getLanguage(),validLoc.getLanguage(),ULOC_LANG_CAPACITY)!=0) { // use DTPG if // * baseLoc has a region and validLoc does not have the same one (or has none), OR diff --git a/icu4c/source/test/cintltst/cdattst.c b/icu4c/source/test/cintltst/cdattst.c index c390f1e4ad6..5459bb5f6cf 100644 --- a/icu4c/source/test/cintltst/cdattst.c +++ b/icu4c/source/test/cintltst/cdattst.c @@ -51,6 +51,7 @@ static void TestNarrowQuarters(void); static void TestExtraneousCharacters(void); static void TestParseTooStrict(void); static void TestHourCycle(void); +static void TestLocaleNameCrash(void); void addDateForTest(TestNode** root); @@ -76,6 +77,7 @@ void addDateForTest(TestNode** root) TESTCASE(TestExtraneousCharacters); TESTCASE(TestParseTooStrict); TESTCASE(TestHourCycle); + TESTCASE(TestLocaleNameCrash); } /* Testing the DateFormat API */ static void TestDateFormat() @@ -2129,4 +2131,17 @@ static void TestHourCycle(void) { } } +static void TestLocaleNameCrash(void) { + UErrorCode status = U_ZERO_ERROR; + UDateFormat icudf; + + icudf = udat_open(UDAT_MEDIUM, UDAT_NONE, "notalanguage", NULL, 0, NULL, 0, &status); + if ( U_SUCCESS(status) ) { + log_verbose("Success: did not crash on udat_open(locale=\"notalanguage\")\n"); + } else { + log_err("FAIL: didn't crash on udat_open(locale=\"notalanguage\"), but got %s.\n", u_errorName(status)); + } + udat_close(icudf); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/intltest/dtfmttst.cpp b/icu4c/source/test/intltest/dtfmttst.cpp index 1e03ffb9ed6..681e5d65497 100644 --- a/icu4c/source/test/intltest/dtfmttst.cpp +++ b/icu4c/source/test/intltest/dtfmttst.cpp @@ -135,6 +135,7 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam TESTCASE_AUTO(TestNumericFieldStrictParse); TESTCASE_AUTO(TestHourCycle); TESTCASE_AUTO(TestHCInLocale); + TESTCASE_AUTO(TestBogusLocale); TESTCASE_AUTO_END; } @@ -5876,6 +5877,14 @@ void DateFormatTest::TestHourCycle() { } } +void DateFormatTest::TestBogusLocale() { + IcuTestErrorCode status(*this, "TestBogusLocale"); + LocalPointer df; + + df.adoptInstead(DateFormat::createDateTimeInstance(DateFormat::kNone, DateFormat::kMedium, + Locale("notalanguage"))); +} + void DateFormatTest::TestHCInLocale() { IcuTestErrorCode status(*this, "TestHCInLocale"); LocalPointer midnight(Calendar::createInstance(status)); diff --git a/icu4c/source/test/intltest/dtfmttst.h b/icu4c/source/test/intltest/dtfmttst.h index cafa7cdae90..4c44929b27c 100644 --- a/icu4c/source/test/intltest/dtfmttst.h +++ b/icu4c/source/test/intltest/dtfmttst.h @@ -270,6 +270,7 @@ public: void TestNumericFieldStrictParse(); void TestHourCycle(); void TestHCInLocale(); + void TestBogusLocale(); private: UBool showParse(DateFormat &format, const UnicodeString &formattedString);