From 27f8d70bcd03b7721916a5795ba62956af5f9ba4 Mon Sep 17 00:00:00 2001 From: Markus Scherer Date: Thu, 14 Dec 2017 21:25:46 +0000 Subject: [PATCH] ICU-13503 declare variable-length array at end of struct with length 1 to disable bounds checkers X-SVN-Rev: 40736 --- icu4c/source/common/rbbi.cpp | 8 ++------ icu4c/source/common/rbbidata.h | 11 +++++++---- icu4c/source/common/rbbitblb.cpp | 15 ++++++--------- icu4c/source/common/ucmndata.cpp | 6 +++++- icu4c/source/common/ucmndata.h | 6 +++++- icu4c/source/i18n/decimalformatpattern.cpp | 10 ++++++---- 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/icu4c/source/common/rbbi.cpp b/icu4c/source/common/rbbi.cpp index 54b289e24d1..a02c48d427e 100644 --- a/icu4c/source/common/rbbi.cpp +++ b/icu4c/source/common/rbbi.cpp @@ -867,9 +867,7 @@ int32_t RuleBasedBreakIterator::handleNext() { // State Transition - move machine to its next state // - // Note: fNextState is defined as uint16_t[2], but we are casting - // a generated RBBI table to RBBIStateTableRow and some tables - // actually have more than 2 categories. + // fNextState is a variable-length array. U_ASSERT(categoryfHeader->fCatCount); state = row->fNextState[category]; /*Not accessing beyond memory*/ row = (RBBIStateTableRow *) @@ -1041,9 +1039,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) { // State Transition - move machine to its next state // - // Note: fNextState is defined as uint16_t[2], but we are casting - // a generated RBBI table to RBBIStateTableRow and some tables - // actually have more than 2 categories. + // fNextState is a variable-length array. U_ASSERT(categoryfHeader->fCatCount); state = row->fNextState[category]; /*Not accessing beyond memory*/ row = (RBBIStateTableRow *) diff --git a/icu4c/source/common/rbbidata.h b/icu4c/source/common/rbbidata.h index bd25e06d201..0e7beb77266 100644 --- a/icu4c/source/common/rbbidata.h +++ b/icu4c/source/common/rbbidata.h @@ -116,9 +116,10 @@ struct RBBIStateTableRow { /* StatusTable of the set of matching */ /* tags (rule status values) */ int16_t fReserved; - uint16_t fNextState[2]; /* Next State, indexed by char category. */ - /* This array does not have two elements */ - /* Array Size is actually fData->fHeader->fCatCount */ + uint16_t fNextState[1]; /* Next State, indexed by char category. */ + /* Variable-length array declared with length 1 */ + /* to disable bounds checkers. */ + /* Array Size is actually fData->fHeader->fCatCount*/ /* CAUTION: see RBBITableBuilder::getTableSize() */ /* before changing anything here. */ }; @@ -129,7 +130,9 @@ struct RBBIStateTable { uint32_t fRowLen; /* Length of a state table row, in bytes. */ uint32_t fFlags; /* Option Flags for this state table */ uint32_t fReserved; /* reserved */ - char fTableData[4]; /* First RBBIStateTableRow begins here. */ + char fTableData[1]; /* First RBBIStateTableRow begins here. */ + /* Variable-length array declared with length 1 */ + /* to disable bounds checkers. */ /* (making it char[] simplifies ugly address */ /* arithmetic for indexing variable length rows.) */ }; diff --git a/icu4c/source/common/rbbitblb.cpp b/icu4c/source/common/rbbitblb.cpp index 0f1a901ffc5..6a7e8f5113c 100644 --- a/icu4c/source/common/rbbitblb.cpp +++ b/icu4c/source/common/rbbitblb.cpp @@ -1095,15 +1095,12 @@ int32_t RBBITableBuilder::getTableSize() const { return 0; } - size = sizeof(RBBIStateTable) - 4; // The header, with no rows to the table. + size = offsetof(RBBIStateTable, fTableData); // The header, with no rows to the table. numRows = fDStates->size(); numCols = fRB->fSetBuilder->getNumCharCategories(); - // Note The declaration of RBBIStateTableRow is for a table of two columns. - // Therefore we subtract two from numCols when determining - // how much storage to add to a row for the total columns. - rowSize = sizeof(RBBIStateTableRow) + sizeof(uint16_t)*(numCols-2); + rowSize = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t)*numCols; size += numRows * rowSize; return size; } @@ -1126,14 +1123,14 @@ void RBBITableBuilder::exportTable(void *where) { return; } - if (fRB->fSetBuilder->getNumCharCategories() > 0x7fff || + int32_t catCount = fRB->fSetBuilder->getNumCharCategories(); + if (catCount > 0x7fff || fDStates->size() > 0x7fff) { *fStatus = U_BRK_INTERNAL_ERROR; return; } - table->fRowLen = sizeof(RBBIStateTableRow) + - sizeof(uint16_t) * (fRB->fSetBuilder->getNumCharCategories() - 2); + table->fRowLen = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t) * catCount; table->fNumStates = fDStates->size(); table->fFlags = 0; if (fRB->fLookAheadHardBreak) { @@ -1152,7 +1149,7 @@ void RBBITableBuilder::exportTable(void *where) { row->fAccepting = (int16_t)sd->fAccepting; row->fLookAhead = (int16_t)sd->fLookAhead; row->fTagIdx = (int16_t)sd->fTagsIdx; - for (col=0; colfSetBuilder->getNumCharCategories(); col++) { + for (col=0; colfNextState[col] = (uint16_t)sd->fDtran->elementAti(col); } } diff --git a/icu4c/source/common/ucmndata.cpp b/icu4c/source/common/ucmndata.cpp index 251c7ba1823..ba2310bb7ab 100644 --- a/icu4c/source/common/ucmndata.cpp +++ b/icu4c/source/common/ucmndata.cpp @@ -77,7 +77,11 @@ typedef struct { typedef struct { uint32_t count; uint32_t reserved; - PointerTOCEntry entry[2]; /* Actual size is from count. */ + /** + * Variable-length array declared with length 1 to disable bounds checkers. + * The actual array length is in the count field. + */ + PointerTOCEntry entry[1]; } PointerTOC; diff --git a/icu4c/source/common/ucmndata.h b/icu4c/source/common/ucmndata.h index cc126d53ac1..c3eba9f4d02 100644 --- a/icu4c/source/common/ucmndata.h +++ b/icu4c/source/common/ucmndata.h @@ -52,7 +52,11 @@ typedef struct { typedef struct { uint32_t count; - UDataOffsetTOCEntry entry[2]; /* Actual size of array is from count. */ + /** + * Variable-length array declared with length 1 to disable bounds checkers. + * The actual array length is in the count field. + */ + UDataOffsetTOCEntry entry[1]; } UDataOffsetTOC; /** diff --git a/icu4c/source/i18n/decimalformatpattern.cpp b/icu4c/source/i18n/decimalformatpattern.cpp index b07bcdd3ccf..4ee5e334411 100644 --- a/icu4c/source/i18n/decimalformatpattern.cpp +++ b/icu4c/source/i18n/decimalformatpattern.cpp @@ -50,10 +50,12 @@ static void syntaxError(const UnicodeString& pattern, parseError.preContext[stop-start] = 0; //for post-context - start = pos+1; - stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEXT_LEN-1)) : - pattern.length(); - pattern.extract(start,stop-start,parseError.postContext,0); + start = pattern.moveIndex32(pos, 1); + stop = pos + U_PARSE_CONTEXT_LEN - 1; + if (stop > pattern.length()) { + stop = pattern.length(); + } + pattern.extract(start, stop - start, parseError.postContext, 0); //null terminate the buffer parseError.postContext[stop-start]= 0; }