Skip to content

Commit

Permalink
ICU-21537 Fix invalid free by long locale name
Browse files Browse the repository at this point in the history
Do not free baseName if it is pointing to fullNameBuffer.

Better Fix
  • Loading branch information
FrankYFTang committed Mar 17, 2021
1 parent 3d7ba65 commit cec7de7
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
9 changes: 5 additions & 4 deletions icu4c/source/common/locid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale)

Locale::~Locale()
{
if (baseName != fullName) {
if ((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
Expand Down Expand Up @@ -466,7 +466,7 @@ Locale& Locale::operator=(const Locale& other) {
}

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) {
Expand Down Expand Up @@ -1850,7 +1850,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize)
{
fIsBogus = FALSE;
/* Free our current storage */
if (baseName != fullName) {
if ((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
Expand Down Expand Up @@ -1886,6 +1886,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize)
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) {
Expand Down Expand Up @@ -2039,7 +2040,7 @@ Locale::hashCode() const
void
Locale::setToBogus() {
/* Free our current storage */
if(baseName != fullName) {
if((baseName != fullName) && (baseName != fullNameBuffer)) {
uprv_free(baseName);
}
baseName = NULL;
Expand Down
10 changes: 10 additions & 0 deletions icu4c/source/test/intltest/collationtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class CollationTest : public IntlTest {
void TestRootElements();
void TestTailoredElements();
void TestDataDriven();
void TestLongLocale();

private:
void checkFCD(const char *name, CollationIterator &ci, CodePointIterator &cpi);
Expand Down Expand Up @@ -148,6 +149,7 @@ void CollationTest::runIndexedTest(int32_t index, UBool exec, const char *&name,
TESTCASE_AUTO(TestRootElements);
TESTCASE_AUTO(TestTailoredElements);
TESTCASE_AUTO(TestDataDriven);
TESTCASE_AUTO(TestLongLocale);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -1852,4 +1854,12 @@ void CollationTest::TestDataDriven() {
}
}

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

0 comments on commit cec7de7

Please sign in to comment.