]> granicus.if.org Git - icu/commitdiff
ICU-13503 declare variable-length array at end of struct with length 1 to disable...
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 14 Dec 2017 21:25:46 +0000 (21:25 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 14 Dec 2017 21:25:46 +0000 (21:25 +0000)
X-SVN-Rev: 40736

icu4c/source/common/rbbi.cpp
icu4c/source/common/rbbidata.h
icu4c/source/common/rbbitblb.cpp
icu4c/source/common/ucmndata.cpp
icu4c/source/common/ucmndata.h
icu4c/source/i18n/decimalformatpattern.cpp

index 54b289e24d1e0affac7f32ec140046c1b57b581d..a02c48d427e68df2244574e7822541c8d47f6f44 100644 (file)
@@ -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(category<fData->fHeader->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(category<fData->fHeader->fCatCount);
         state = row->fNextState[category];  /*Not accessing beyond memory*/
         row = (RBBIStateTableRow *)
index bd25e06d201c6e1c9ce937b49581fce5bece83a3..0e7beb7726694c775e58b800ed04bd49a1513416 100644 (file)
@@ -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.) */
 };
index 0f1a901ffc542261bce396c0e362e1c20bfeddba..6a7e8f5113c1f06d55daeb66611119e7e3c114ca 100644 (file)
@@ -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; col<fRB->fSetBuilder->getNumCharCategories(); col++) {
+        for (col=0; col<catCount; col++) {
             row->fNextState[col] = (uint16_t)sd->fDtran->elementAti(col);
         }
     }
index 251c7ba1823887d47fbae202e6abe238ccf09ceb..ba2310bb7ab8a5c5e470373b6df0d35f86418ab8 100644 (file)
@@ -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;
 
 
index cc126d53ac1c7c493d9284c8c1bd20c1e30194f1..c3eba9f4d021022a41e41dad37bf8a9dbfdef09e 100644 (file)
@@ -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;
 
 /**
index b07bcdd3ccff6f7f8c122700369ad14d4a5f0674..4ee5e334411706860c208f8680b6e959f05b7b5c 100644 (file)
@@ -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;
 }