diff --git a/icu4c/source/common/unames.cpp b/icu4c/source/common/unames.cpp index e6fa30f3bd9..a2035c48dfc 100644 --- a/icu4c/source/common/unames.cpp +++ b/icu4c/source/common/unames.cpp @@ -1554,15 +1554,16 @@ u_charFromName(UCharNameChoice nameChoice, *pErrorCode = U_ILLEGAL_CHAR_FOUND; return error; } + // i==strlen(name)==strlen(lower)==strlen(upper) /* try extended names first */ if (lower[0] == '<') { if (nameChoice == U_EXTENDED_CHAR_NAME) { - if (lower[--i] == '>') { - for (--i; lower[i] && lower[i] != '-'; --i) { - } + // Parse a string like "" where HHHH is a hex code point. + if (lower[--i] == '>' && i >= 3 && lower[--i] != '-') { + while (i >= 3 && lower[--i] != '-') {} - if (lower[i] == '-') { /* We've got a category. */ + if (i >= 2 && lower[i] == '-') { uint32_t cIdx; lower[i] = 0; diff --git a/icu4c/source/test/cintltst/cucdtst.c b/icu4c/source/test/cintltst/cucdtst.c index 72feba8c522..b7ea2740440 100644 --- a/icu4c/source/test/cintltst/cucdtst.c +++ b/icu4c/source/test/cintltst/cucdtst.c @@ -49,6 +49,7 @@ static void TestCodeUnit(void); static void TestCodePoint(void); static void TestCharLength(void); static void TestCharNames(void); +static void TestUCharFromNameUnderflow(void); static void TestMirroring(void); static void TestUScriptRunAPI(void); static void TestAdditionalProperties(void); @@ -183,6 +184,7 @@ void addUnicodeTest(TestNode** root) addTest(root, &TestControlPrint, "tsutil/cucdtst/TestControlPrint"); addTest(root, &TestIdentifier, "tsutil/cucdtst/TestIdentifier"); addTest(root, &TestCharNames, "tsutil/cucdtst/TestCharNames"); + addTest(root, &TestUCharFromNameUnderflow, "tsutil/cucdtst/TestUCharFromNameUnderflow"); addTest(root, &TestMirroring, "tsutil/cucdtst/TestMirroring"); addTest(root, &TestUScriptCodeAPI, "tsutil/cucdtst/TestUScriptCodeAPI"); addTest(root, &TestHasScript, "tsutil/cucdtst/TestHasScript"); @@ -1937,6 +1939,35 @@ TestCharNames() { /* ### TODO: test error cases and other interesting things */ } +static void +TestUCharFromNameUnderflow() { + // Ticket #10889: Underflow crash when there is no dash. + UErrorCode errorCode=U_ZERO_ERROR; + UChar32 c=u_charFromName(U_EXTENDED_CHAR_NAME, "", &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("u_charFromName() = U+%04x but should fail - %s\n", c, u_errorName(errorCode)); + } + + // Test related edge cases. + errorCode=U_ZERO_ERROR; + c=u_charFromName(U_EXTENDED_CHAR_NAME, "<-00a0>", &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("u_charFromName(<-00a0>) = U+%04x but should fail - %s\n", c, u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + c=u_charFromName(U_EXTENDED_CHAR_NAME, "", &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("u_charFromName() = U+%04x but should fail - %s\n", c, u_errorName(errorCode)); + } + + errorCode=U_ZERO_ERROR; + c=u_charFromName(U_EXTENDED_CHAR_NAME, "", &errorCode); + if(U_SUCCESS(errorCode)) { + log_err("u_charFromName() = U+%04x but should fail - %s\n", c, u_errorName(errorCode)); + } +} + /* test u_isMirrored() and u_charMirror() ----------------------------------- */ static void