From 5991c9392c41369c9d4e9f7dd808b5b5b9a8c7fe Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 19 Sep 2024 12:57:39 -0700 Subject: [PATCH] ICU-22890 MF2: Add ICU4C test for lone surrogates Add a test to ICU4C for handling of lone surrogates. Incidentally fix uninitialized-memory bug in MessageFormatter (initialize `errors` to nullptr) Co-authored-by: Frank Tang --- .../test/intltest/messageformat2test.cpp | 30 +++++++++++++++++++ .../source/test/intltest/messageformat2test.h | 2 ++ 2 files changed, 32 insertions(+) diff --git a/icu4c/source/test/intltest/messageformat2test.cpp b/icu4c/source/test/intltest/messageformat2test.cpp index 8a806ce69bf7..353082ef5c91 100644 --- a/icu4c/source/test/intltest/messageformat2test.cpp +++ b/icu4c/source/test/intltest/messageformat2test.cpp @@ -31,6 +31,8 @@ TestMessageFormat2::runIndexedTest(int32_t index, UBool exec, TESTCASE_AUTO(testAPISimple); TESTCASE_AUTO(testDataModelAPI); TESTCASE_AUTO(testFormatterAPI); + TESTCASE_AUTO(testHighLoneSurrogate); + TESTCASE_AUTO(testLowLoneSurrogate); TESTCASE_AUTO(dataDrivenTests); TESTCASE_AUTO_END; } @@ -337,6 +339,34 @@ void TestMessageFormat2::testAPICustomFunctions() { delete person; } +// ICU-22890 lone surrogate cause infinity loop +void TestMessageFormat2::testHighLoneSurrogate() { + IcuTestErrorCode errorCode(*this, "testHighLoneSurrogate"); + UParseError pe = { 0, 0, {0}, {0} }; + // Lone surrogate with only high surrogate + UnicodeString loneSurrogate({0xda02, 0}); + icu::message2::MessageFormatter msgfmt1 = + icu::message2::MessageFormatter::Builder(errorCode) + .setPattern(loneSurrogate, pe, errorCode) + .build(errorCode); + UnicodeString result = msgfmt1.formatToString({}, errorCode); + errorCode.expectErrorAndReset(U_MF_SYNTAX_ERROR, "testHighLoneSurrogate"); +} + +// ICU-22890 lone surrogate cause infinity loop +void TestMessageFormat2::testLowLoneSurrogate() { + IcuTestErrorCode errorCode(*this, "testLowLoneSurrogate"); + UParseError pe = { 0, 0, {0}, {0} }; + // Lone surrogate with only low surrogate + UnicodeString loneSurrogate({0xdc02, 0}); + icu::message2::MessageFormatter msgfmt2 = + icu::message2::MessageFormatter::Builder(errorCode) + .setPattern(loneSurrogate, pe, errorCode) + .build(errorCode); + UnicodeString result = msgfmt2.formatToString({}, errorCode); + errorCode.expectErrorAndReset(U_MF_SYNTAX_ERROR, "testLowLoneSurrogate"); +} + void TestMessageFormat2::dataDrivenTests() { IcuTestErrorCode errorCode(*this, "jsonTests"); diff --git a/icu4c/source/test/intltest/messageformat2test.h b/icu4c/source/test/intltest/messageformat2test.h index c21c1751c4f4..71dfb3916c9b 100644 --- a/icu4c/source/test/intltest/messageformat2test.h +++ b/icu4c/source/test/intltest/messageformat2test.h @@ -89,6 +89,8 @@ class TestMessageFormat2: public IntlTest { void testMessageFormatDateTimeSkeleton(message2::TestCase::Builder&, IcuTestErrorCode&); void testMf1Behavior(message2::TestCase::Builder&, IcuTestErrorCode&); + void testHighLoneSurrogate(void); + void testLowLoneSurrogate(void); }; // class TestMessageFormat2 U_NAMESPACE_BEGIN