ICU-2190 fix crashing bug in RBBI rule builder

X-SVN-Rev: 9813
This commit is contained in:
Andy Heninger 2002-08-29 00:28:11 +00:00
parent d2e6ab9355
commit 5780aed3d3
5 changed files with 53 additions and 16 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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*/
}
}

View file

@ -73,6 +73,8 @@ public:
*/
void TestWordStatus();
void TestBug2190();
/**
*Internal subroutines
**/