From 73f972f7ff1a7799e70195cfbceff2ac32229169 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Thu, 7 Dec 2023 15:07:27 -0800 Subject: [PATCH] ICU-22581 Fix RBBI leakage Duplicate variable references in the rule should not cause leakage --- icu4c/source/common/rbbiscan.cpp | 8 ++++++++ icu4c/source/test/intltest/rbbitst.cpp | 9 +++++++++ icu4c/source/test/intltest/rbbitst.h | 1 + 3 files changed, 18 insertions(+) diff --git a/icu4c/source/common/rbbiscan.cpp b/icu4c/source/common/rbbiscan.cpp index 844b0639099c..336cd943702a 100644 --- a/icu4c/source/common/rbbiscan.cpp +++ b/icu4c/source/common/rbbiscan.cpp @@ -289,6 +289,9 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) // Terminate expression, leaves expression parse tree rooted in TOS node. fixOpStack(RBBINode::precStart); + if (U_FAILURE(*fRB->fStatus)) { + break; + } RBBINode *startExprNode = fNodeStack[fNodeStackPtr-2]; RBBINode *varRefNode = fNodeStack[fNodeStackPtr-1]; @@ -312,6 +315,11 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) UErrorCode t = *fRB->fStatus; *fRB->fStatus = U_ZERO_ERROR; error(t); + // When adding $variableRef to the symbol table fail, Delete + // both nodes because deleting varRefNode will not delete + // RHSExprNode internally. + delete RHSExprNode; + delete varRefNode; } // Clean up the stack. diff --git a/icu4c/source/test/intltest/rbbitst.cpp b/icu4c/source/test/intltest/rbbitst.cpp index dcfff8a54a90..16f1ea8081c7 100644 --- a/icu4c/source/test/intltest/rbbitst.cpp +++ b/icu4c/source/test/intltest/rbbitst.cpp @@ -144,6 +144,7 @@ void RBBITest::runIndexedTest( int32_t index, UBool exec, const char* &name, cha TESTCASE_AUTO(TestRandomAccess); TESTCASE_AUTO(TestExternalBreakEngineWithFakeTaiLe); TESTCASE_AUTO(TestExternalBreakEngineWithFakeYue); + TESTCASE_AUTO(TestBug22581); TESTCASE_AUTO(TestBug22584); #if U_ENABLE_TRACING @@ -5873,4 +5874,12 @@ void RBBITest::TestBug22584() { RuleBasedBreakIterator bi(ruleStr, pe, ec); } +void RBBITest::TestBug22581() { + // Test duplicate variable setting will not leak the rule compilation + UnicodeString ruleStr = u"$foo=[abc]; $foo=[xyz]; $foo;"; + UParseError pe {}; + UErrorCode ec {U_ZERO_ERROR}; + + RuleBasedBreakIterator bi(ruleStr, pe, ec); +} #endif // #if !UCONFIG_NO_BREAK_ITERATION diff --git a/icu4c/source/test/intltest/rbbitst.h b/icu4c/source/test/intltest/rbbitst.h index 9f85b273ae1b..79bf5091d3cb 100644 --- a/icu4c/source/test/intltest/rbbitst.h +++ b/icu4c/source/test/intltest/rbbitst.h @@ -98,6 +98,7 @@ class RBBITest: public IntlTest { void TestRandomAccess(); void TestExternalBreakEngineWithFakeTaiLe(); void TestExternalBreakEngineWithFakeYue(); + void TestBug22581(); void TestBug22584(); #if U_ENABLE_TRACING