From 44dee82dfd879f19e8dda659a02b414ca5c6b0ac Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Mon, 13 Feb 2017 21:04:32 +0000 Subject: [PATCH] ICU-12932 RBBI rule parsing, fix incorrect handling of node stack overflow. X-SVN-Rev: 39669 --- icu4c/source/common/rbbiscan.cpp | 7 +++---- icu4c/source/test/intltest/rbbitst.cpp | 22 +++++++++++++++++++++- icu4c/source/test/intltest/rbbitst.h | 1 + 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/icu4c/source/common/rbbiscan.cpp b/icu4c/source/common/rbbiscan.cpp index 060c0df629..e68e0529d0 100644 --- a/icu4c/source/common/rbbiscan.cpp +++ b/icu4c/source/common/rbbiscan.cpp @@ -1179,13 +1179,12 @@ RBBINode *RBBIRuleScanner::pushNewNode(RBBINode::NodeType t) { if (U_FAILURE(*fRB->fStatus)) { return NULL; } - fNodeStackPtr++; - if (fNodeStackPtr >= kStackSize) { - error(U_BRK_INTERNAL_ERROR); + if (fNodeStackPtr >= kStackSize - 1) { + error(U_BRK_RULE_SYNTAX); RBBIDebugPuts("RBBIRuleScanner::pushNewNode - stack overflow."); - *fRB->fStatus = U_BRK_INTERNAL_ERROR; return NULL; } + fNodeStackPtr++; fNodeStack[fNodeStackPtr] = new RBBINode(t); if (fNodeStack[fNodeStackPtr] == NULL) { *fRB->fStatus = U_MEMORY_ALLOCATION_ERROR; diff --git a/icu4c/source/test/intltest/rbbitst.cpp b/icu4c/source/test/intltest/rbbitst.cpp index 5d8295014b..a893f5c648 100644 --- a/icu4c/source/test/intltest/rbbitst.cpp +++ b/icu4c/source/test/intltest/rbbitst.cpp @@ -104,6 +104,7 @@ void RBBITest::runIndexedTest( int32_t index, UBool exec, const char* &name, cha TESTCASE_AUTO(TestBug7547); TESTCASE_AUTO(TestBug12797); TESTCASE_AUTO(TestBug12918); + TESTCASE_AUTO(TestBug12932); TESTCASE_AUTO_END; } @@ -4665,13 +4666,32 @@ void RBBITest::TestBug12918() { ubrk_close(iter); } +void RBBITest::TestBug12932() { + // Node Stack overflow in the RBBI rule parser caused a seg fault. + UnicodeString ruleStr( + "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" + "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))" + ")))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))" + ")))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))" + ")))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"); + + UErrorCode status = U_ZERO_ERROR; + UParseError parseError; + RuleBasedBreakIterator rbbi(ruleStr, parseError, status); + if (status != U_BRK_RULE_SYNTAX) { + errln("%s:%d expected U_BRK_RULE_SYNTAX, got %s", + __FILE__, __LINE__, u_errorName(status)); + } +} + + // // TestDebug - A place-holder test for debugging purposes. // For putting in fragments of other tests that can be invoked // for tracing without a lot of unwanted extra stuff happening. // void RBBITest::TestDebug(void) { - } void RBBITest::TestProperties() { diff --git a/icu4c/source/test/intltest/rbbitst.h b/icu4c/source/test/intltest/rbbitst.h index d22b416d48..025d3028d2 100644 --- a/icu4c/source/test/intltest/rbbitst.h +++ b/icu4c/source/test/intltest/rbbitst.h @@ -77,6 +77,7 @@ public: void TestBug7547(); void TestBug12797(); void TestBug12918(); + void TestBug12932(); void TestDebug(); void TestProperties();