ICU-21537 Fix invalid free by long locale name
Do not free baseName if it is pointing to fullNameBuffer.
Better Fix
diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
index 5d60435..e16fbb7 100644
--- a/icu4c/source/common/locid.cpp
+++ b/icu4c/source/common/locid.cpp
@@ -254,7 +254,7 @@
Locale::~Locale()
{
- if (baseName != fullName) {
+ if ((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
@@ -466,7 +466,7 @@
}
Locale& Locale::operator=(Locale&& other) U_NOEXCEPT {
- if (baseName != fullName) uprv_free(baseName);
+ if ((baseName != fullName) && (baseName != fullNameBuffer)) uprv_free(baseName);
if (fullName != fullNameBuffer) uprv_free(fullName);
if (other.fullName == other.fullNameBuffer) {
@@ -1850,7 +1850,7 @@
{
fIsBogus = FALSE;
/* Free our current storage */
- if (baseName != fullName) {
+ if ((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
@@ -1886,6 +1886,7 @@
uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameBuffer)) {
+ U_ASSERT(baseName == nullptr);
/*Go to heap for the fullName if necessary*/
fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
if(fullName == 0) {
@@ -2039,7 +2040,7 @@
void
Locale::setToBogus() {
/* Free our current storage */
- if(baseName != fullName) {
+ if((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
diff --git a/icu4c/source/test/intltest/collationtest.cpp b/icu4c/source/test/intltest/collationtest.cpp
index de51eec..4f1fee9 100644
--- a/icu4c/source/test/intltest/collationtest.cpp
+++ b/icu4c/source/test/intltest/collationtest.cpp
@@ -78,6 +78,7 @@
void TestRootElements();
void TestTailoredElements();
void TestDataDriven();
+ void TestLongLocale();
private:
void checkFCD(const char *name, CollationIterator &ci, CodePointIterator &cpi);
@@ -148,6 +149,7 @@
TESTCASE_AUTO(TestRootElements);
TESTCASE_AUTO(TestTailoredElements);
TESTCASE_AUTO(TestDataDriven);
+ TESTCASE_AUTO(TestLongLocale);
TESTCASE_AUTO_END;
}
@@ -1852,4 +1854,12 @@
}
}
+void CollationTest::TestLongLocale() {
+ IcuTestErrorCode errorCode(*this, "TestLongLocale");
+ Locale longLocale("sie__1G_C_CEIE_CEZCX_CSUE_E_EIESZNI2_GB_LM_LMCSUE_LMCSX_"
+ "LVARIANT_MMCSIE_STEU_SU1GCEIE_SU6G_SU6SU6G_U_UBGE_UC_"
+ "UCEZCSI_UCIE_UZSIU_VARIANT_X@collation=bcs-ukvsz");
+ LocalPointer<Collator> coll(Collator::createInstance(longLocale, errorCode));
+}
+
#endif // !UCONFIG_NO_COLLATION