diff --git a/icu4c/source/common/ubidi.c b/icu4c/source/common/ubidi.c index f17d5f1a9eb..b62b7df9081 100644 --- a/icu4c/source/common/ubidi.c +++ b/icu4c/source/common/ubidi.c @@ -679,10 +679,10 @@ bracketInit(UBiDi *pBiDi, BracketData *bd) { bd->isoRuns[0].contextPos=0; if(pBiDi->openingsMemory) { bd->openings=pBiDi->openingsMemory; - bd->openingsSize=pBiDi->openingsSize; + bd->openingsCount=pBiDi->openingsSize / sizeof(Opening); } else { bd->openings=bd->simpleOpenings; - bd->openingsSize=SIMPLE_OPENINGS_SIZE; + bd->openingsCount=SIMPLE_OPENINGS_SIZE; } bd->isNumbersSpecial=bd->pBiDi->reorderingMode==UBIDI_REORDER_NUMBERS_SPECIAL || bd->pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL; @@ -743,7 +743,7 @@ static UBool /* return TRUE if success */ bracketAddOpening(BracketData *bd, UChar match, int32_t position) { IsoRun *pLastIsoRun=&bd->isoRuns[bd->isoRunLast]; Opening *pOpening; - if(pLastIsoRun->limit>=bd->openingsSize) { /* no available new entry */ + if(pLastIsoRun->limit>=bd->openingsCount) { /* no available new entry */ UBiDi *pBiDi=bd->pBiDi; if(!getInitialOpeningsMemory(pBiDi, pLastIsoRun->limit * 2)) return FALSE; @@ -751,7 +751,7 @@ bracketAddOpening(BracketData *bd, UChar match, int32_t position) { uprv_memcpy(pBiDi->openingsMemory, bd->simpleOpenings, SIMPLE_OPENINGS_SIZE * sizeof(Opening)); bd->openings=pBiDi->openingsMemory; /* may have changed */ - bd->openingsSize=pBiDi->openingsSize; + bd->openingsCount=pBiDi->openingsSize / sizeof(Opening); } pOpening=&bd->openings[pLastIsoRun->limit]; pOpening->position=position; diff --git a/icu4c/source/common/ubidiimp.h b/icu4c/source/common/ubidiimp.h index 21a7d5e265b..6db5b44c17a 100644 --- a/icu4c/source/common/ubidiimp.h +++ b/icu4c/source/common/ubidiimp.h @@ -173,7 +173,7 @@ typedef struct BracketData { /* array of opening entries which should be enough in most cases; no malloc() */ Opening simpleOpenings[SIMPLE_OPENINGS_SIZE]; Opening *openings; /* pointer to current array of entries */ - int32_t openingsSize; /* number of allocated entries */ + int32_t openingsCount; /* number of allocated entries */ int32_t isoRunLast; /* index of last used entry */ /* array of nested isolated sequence entries; can never excess UBIDI_MAX_EXPLICIT_LEVEL + 1 for index 0, + 1 for before the first isolated sequence */ diff --git a/icu4c/source/test/cintltst/cbiditst.c b/icu4c/source/test/cintltst/cbiditst.c index c6252360c70..b1d1ede56c4 100644 --- a/icu4c/source/test/cintltst/cbiditst.c +++ b/icu4c/source/test/cintltst/cbiditst.c @@ -87,6 +87,8 @@ static void testContext(void); static void doTailTest(void); +static void testBracketOverflow(void); + /* new BIDI API */ static void testReorderingMode(void); static void testReorderRunsOnly(void); @@ -133,6 +135,7 @@ addComplexTest(TestNode** root) { addTest(root, testClassOverride, "complex/bidi/TestClassOverride"); addTest(root, testGetBaseDirection, "complex/bidi/testGetBaseDirection"); addTest(root, testContext, "complex/bidi/testContext"); + addTest(root, testBracketOverflow, "complex/bidi/TestBracketOverflow"); addTest(root, doArabicShapingTest, "complex/arabic-shaping/ArabicShapingTest"); addTest(root, doLamAlefSpecialVLTRArabicShapingTest, "complex/arabic-shaping/lamalef"); @@ -4896,3 +4899,25 @@ testContext(void) { log_verbose("\nExiting TestContext \n\n"); } + +/* Ticket#11054 ubidi_setPara crash with heavily nested brackets */ +static void +testBracketOverflow(void) { + static const char* TEXT = "(((((((((((((((((((((((((((((((((((((((((a)(A)))))))))))))))))))))))))))))))))))))))))"; + UErrorCode status = U_ZERO_ERROR; + UBiDi* bidi; + UChar src[100]; + UChar dest[100]; + int32_t len; + + bidi = ubidi_open(); + len = uprv_strlen(TEXT); + pseudoToU16(len, TEXT, src); + ubidi_setPara(bidi, src, len, UBIDI_DEFAULT_LTR , NULL, &status); + if (U_FAILURE(status)) { + log_err("setPara failed with heavily nested brackets - %s", u_errorName(status)); + } + + ubidi_close(bidi); +} +