ICU-22798 Avoid stack overflow by return error.

See #3035
This commit is contained in:
Frank Yung-Fong Tang 2024-06-13 22:44:12 +00:00 committed by Rahul Pandey
parent b82291fd77
commit 697cb14f08
4 changed files with 21 additions and 1 deletions

View file

@ -437,7 +437,7 @@ MessagePattern::parseMessage(int32_t index, int32_t msgStartLength,
if(U_FAILURE(errorCode)) {
return 0;
}
if(nestingLevel>Part::MAX_VALUE) {
if(nestingLevel>Part::MAX_NESTED_LEVELS) {
errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
return 0;
}

View file

@ -821,6 +821,7 @@ public:
static const int32_t MAX_LENGTH=0xffff;
static const int32_t MAX_VALUE=0x7fff;
static const int32_t MAX_NESTED_LEVELS=0x03ff;
// Some fields are not final because they are modified during pattern parsing.
// After pattern parsing, the parts are effectively immutable.

View file

@ -54,6 +54,7 @@ MessageFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const ch
TESTCASE_AUTO(TestChoicePatternQuote);
TESTCASE_AUTO(Test4112104);
TESTCASE_AUTO(TestICU12584);
TESTCASE_AUTO(TestICU22798);
TESTCASE_AUTO(TestAPI);
TESTCASE_AUTO_END;
}
@ -1013,6 +1014,23 @@ void MessageFormatRegressionTest::TestICU12584() {
inner_msg.getFormats(count);
assertEquals("Inner placeholder match", 3, count);
}
void MessageFormatRegressionTest::TestICU22798() {
// Test deep nested choice will not cause stack overflow but return error
// instead.
UErrorCode status = U_ZERO_ERROR;
UnicodeString pattern;
constexpr static int testNestedLevel = 30000;
for (int i = 0; i < testNestedLevel; i++) {
pattern += u"A{0,choice,0#";
}
pattern += u"text";
for (int i = 0; i < testNestedLevel; i++) {
pattern += u"}a";
}
MessageFormat msg(pattern, status);
assertEquals("Deep nested choice should cause error but not crash",
U_INDEX_OUTOFBOUNDS_ERROR, status);
}
void MessageFormatRegressionTest::TestAPI() {
UErrorCode status = U_ZERO_ERROR;

View file

@ -46,6 +46,7 @@ public:
void TestChoicePatternQuote();
void Test4112104();
void TestICU12584();
void TestICU22798();
void TestAPI();
protected: