mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-2190 fix crashing bug in RBBI rule builder
X-SVN-Rev: 9813
This commit is contained in:
parent
d2e6ab9355
commit
5780aed3d3
5 changed files with 53 additions and 16 deletions
|
@ -162,14 +162,22 @@ RBBINode *RBBINode::cloneTree() {
|
|||
// references with a copy of the variable's definition.
|
||||
// Aside from variables, the tree is not changed.
|
||||
//
|
||||
// Return the root of the tree. If the root was not a variable
|
||||
// reference, it remains unchanged - the root we started with
|
||||
// is the root we return. If, however, the root was a variable
|
||||
// reference, the root of the newly cloned replacement tree will
|
||||
// be returned.
|
||||
//
|
||||
// This function works by recursively walking the tree
|
||||
// without doing anything until a variable reference is
|
||||
// found, then calling cloneTree() at that point. Any
|
||||
// nested references are handled by cloneTree(), not here.
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
void RBBINode::flattenVariables() {
|
||||
U_ASSERT(fType != varRef);
|
||||
RBBINode *RBBINode::flattenVariables() {
|
||||
if (fType == varRef) {
|
||||
return fLeftChild->cloneTree();
|
||||
}
|
||||
|
||||
if (fLeftChild != NULL) {
|
||||
if (fLeftChild->fType==varRef) {
|
||||
|
@ -181,7 +189,7 @@ void RBBINode::flattenVariables() {
|
|||
fLeftChild->flattenVariables();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fRightChild != NULL) {
|
||||
if (fRightChild->fType==varRef) {
|
||||
RBBINode *oldChild = fRightChild;
|
||||
|
@ -192,6 +200,7 @@ void RBBINode::flattenVariables() {
|
|||
fRightChild->flattenVariables();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ class RBBINode : public UObject {
|
|||
~RBBINode();
|
||||
|
||||
RBBINode *cloneTree();
|
||||
void flattenVariables();
|
||||
RBBINode *flattenVariables();
|
||||
void flattenSets();
|
||||
void findNodes(UVector *dest, RBBINode::NodeType kind, UErrorCode &status);
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ void RBBITableBuilder::build() {
|
|||
// Walk through the tree, replacing any references to $variables with a copy of the
|
||||
// parse tree for the substition expression.
|
||||
//
|
||||
fTree->flattenVariables();
|
||||
fTree = fTree->flattenVariables();
|
||||
if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ftree")) {
|
||||
RBBIDebugPrintf("Parse tree after flattening variable references.\n");
|
||||
fTree->printTree(TRUE);
|
||||
|
|
|
@ -690,6 +690,31 @@ void RBBIAPITest::TestWordStatus() {
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// Bug 2190 Regression test. Builder crash on rule consisting of only a
|
||||
// $variable reference
|
||||
void RBBIAPITest::TestBug2190() {
|
||||
UnicodeString rulesString1 = "$aaa = abcd;\n"
|
||||
"$bbb = $aaa;\n"
|
||||
"$bbb;\n";
|
||||
UnicodeString testString1 = "abcdabcd";
|
||||
// 01234567890
|
||||
int32_t bounds1[] = {0, 4, 8};
|
||||
UErrorCode status=U_ZERO_ERROR;
|
||||
UParseError parseError;
|
||||
|
||||
RuleBasedBreakIterator *bi = new RuleBasedBreakIterator(rulesString1, parseError, status);
|
||||
if(U_FAILURE(status)) {
|
||||
errln("FAIL : in construction");
|
||||
} else {
|
||||
bi->setText(testString1);
|
||||
doBoundaryTest(*bi, testString1, bounds1);
|
||||
}
|
||||
delete bi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------
|
||||
// runIndexedTest
|
||||
//---------------------------------------------
|
||||
|
@ -699,17 +724,18 @@ void RBBIAPITest::runIndexedTest( int32_t index, UBool exec, const char* &name,
|
|||
if (exec) logln((UnicodeString)"TestSuite RuleBasedBreakIterator API ");
|
||||
switch (index) {
|
||||
// case 0: name = "TestConstruction"; if (exec) TestConstruction(); break;
|
||||
case 0: name = "TestCloneEquals"; if (exec) TestCloneEquals(); break;
|
||||
case 1: name = "TestgetRules"; if (exec) TestgetRules(); break;
|
||||
case 2: name = "TestHashCode"; if (exec) TestHashCode(); break;
|
||||
case 3: name = "TestGetSetAdoptText"; if (exec) TestGetSetAdoptText(); break;
|
||||
case 4: name = "TestFirstNextFollowing"; if (exec) TestFirstNextFollowing(); break;
|
||||
case 5: name = "TestLastPreviousPreceding"; if (exec) TestLastPreviousPreceding(); break;
|
||||
case 6: name = "TestIsBoundary"; if (exec) TestIsBoundary(); break;
|
||||
case 7: name = "TestBuilder"; if (exec) TestBuilder(); break;
|
||||
case 8: name = "TestQuoteGrouping"; if (exec) TestQuoteGrouping(); break;
|
||||
case 9: name = "TestWordStatus"; if (exec) TestWordStatus(); break;
|
||||
|
||||
case 0: name = "TestCloneEquals"; if (exec) TestCloneEquals(); break;
|
||||
case 1: name = "TestgetRules"; if (exec) TestgetRules(); break;
|
||||
case 2: name = "TestHashCode"; if (exec) TestHashCode(); break;
|
||||
case 3: name = "TestGetSetAdoptText"; if (exec) TestGetSetAdoptText(); break;
|
||||
case 4: name = "TestFirstNextFollowing"; if (exec) TestFirstNextFollowing(); break;
|
||||
case 5: name = "TestLastPreviousPreceding"; if (exec) TestLastPreviousPreceding(); break;
|
||||
case 6: name = "TestIsBoundary"; if (exec) TestIsBoundary(); break;
|
||||
case 7: name = "TestBuilder"; if (exec) TestBuilder(); break;
|
||||
case 8: name = "TestQuoteGrouping"; if (exec) TestQuoteGrouping(); break;
|
||||
case 9: name = "TestWordStatus"; if (exec) TestWordStatus(); break;
|
||||
case 10: name = "TestBug2190"; if (exec) TestBug2190(); break;
|
||||
|
||||
default: name = ""; break; /*needed to end loop*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ public:
|
|||
*/
|
||||
void TestWordStatus();
|
||||
|
||||
void TestBug2190();
|
||||
|
||||
/**
|
||||
*Internal subroutines
|
||||
**/
|
||||
|
|
Loading…
Add table
Reference in a new issue