ICU-21676 Fix strcpy buffer override in ultag_parse

See #1767
This commit is contained in:
Frank Yung-Fong Tang 2021-07-14 00:47:01 +00:00
parent 24778dfc9b
commit cfffa2b83b
3 changed files with 27 additions and 1 deletions

View file

@ -2089,6 +2089,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta
legacyLen = checkLegacyLen; /* back up for output parsedLen */
int32_t replacementLen = static_cast<int32_t>(uprv_strlen(LEGACY[i+1]));
newTagLength = replacementLen + tagLen - checkLegacyLen;
int32_t oldTagLength = tagLen;
if (tagLen < newTagLength) {
uprv_free(tagBuf);
tagBuf = (char*)uprv_malloc(newTagLength + 1);
@ -2102,7 +2103,10 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta
parsedLenDelta = checkLegacyLen - replacementLen;
uprv_strcpy(t->buf, LEGACY[i + 1]);
if (checkLegacyLen != tagLen) {
uprv_strcpy(t->buf + replacementLen, tag + checkLegacyLen);
uprv_memcpy(t->buf + replacementLen, tag + checkLegacyLen,
oldTagLength - checkLegacyLen);
// NUL-terminate after memcpy().
t->buf[replacementLen + oldTagLength - checkLegacyLen] = 0;
}
break;
}

View file

@ -265,6 +265,7 @@ void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, c
TESTCASE_AUTO(TestKnownCanonicalizedListCorrect);
TESTCASE_AUTO(TestConstructorAcceptsBCP47);
TESTCASE_AUTO(TestForLanguageTag);
TESTCASE_AUTO(TestForLanguageTagLegacyTagBug21676);
TESTCASE_AUTO(TestToLanguageTag);
TESTCASE_AUTO(TestToLanguageTagOmitTrue);
TESTCASE_AUTO(TestMoveAssign);
@ -5677,6 +5678,26 @@ void LocaleTest::TestForLanguageTag() {
}
}
void LocaleTest::TestForLanguageTagLegacyTagBug21676() {
IcuTestErrorCode status(*this, "TestForLanguageTagLegacyTagBug21676()");
std::string tag(
"i-enochian-1nochian-129-515VNTR-64863775-X3il6-110Y101-29-515VNTR-"
"64863775-153zu-u-Y4-H0-t6-X3-u6-110Y101-X");
std::string input(tag);
input += "EXTRA MEMORY AFTER NON-NULL TERMINATED STRING";
StringPiece stringp(input.c_str(), tag.length());
std::string name = Locale::forLanguageTag(stringp, status).getName();
std::string expected(
"@x=i-enochian-1nochian-129-515vntr-64863775-x3il6-110y101-29-515vntr-"
"64863775-153zu-u-y4-h0-t6-x3-u6-110y101-x");
if (name != expected) {
errcheckln(
status,
"FAIL: forLanguageTag('%s', \n%d).getName() should be \n'%s' but got %s",
tag.c_str(), tag.length(), expected.c_str(), name.c_str());
}
}
void LocaleTest::TestToLanguageTag() {
IcuTestErrorCode status(*this, "TestToLanguageTag()");

View file

@ -133,6 +133,7 @@ public:
void TestAddLikelyAndMinimizeSubtags();
void TestForLanguageTag();
void TestForLanguageTagLegacyTagBug21676();
void TestToLanguageTag();
void TestToLanguageTagOmitTrue();