ICU-13503 declare variable-length array at end of struct with length 1 to disable bounds checkers

X-SVN-Rev: 40736
This commit is contained in:
Markus Scherer 2017-12-14 21:25:46 +00:00
parent 3bbf68ff4e
commit 27f8d70bcd
6 changed files with 31 additions and 25 deletions

View File

@ -867,9 +867,7 @@ int32_t RuleBasedBreakIterator::handleNext() {
// State Transition - move machine to its next state // State Transition - move machine to its next state
// //
// Note: fNextState is defined as uint16_t[2], but we are casting // fNextState is a variable-length array.
// a generated RBBI table to RBBIStateTableRow and some tables
// actually have more than 2 categories.
U_ASSERT(category<fData->fHeader->fCatCount); U_ASSERT(category<fData->fHeader->fCatCount);
state = row->fNextState[category]; /*Not accessing beyond memory*/ state = row->fNextState[category]; /*Not accessing beyond memory*/
row = (RBBIStateTableRow *) row = (RBBIStateTableRow *)
@ -1041,9 +1039,7 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) {
// State Transition - move machine to its next state // State Transition - move machine to its next state
// //
// Note: fNextState is defined as uint16_t[2], but we are casting // fNextState is a variable-length array.
// a generated RBBI table to RBBIStateTableRow and some tables
// actually have more than 2 categories.
U_ASSERT(category<fData->fHeader->fCatCount); U_ASSERT(category<fData->fHeader->fCatCount);
state = row->fNextState[category]; /*Not accessing beyond memory*/ state = row->fNextState[category]; /*Not accessing beyond memory*/
row = (RBBIStateTableRow *) row = (RBBIStateTableRow *)

View File

@ -116,9 +116,10 @@ struct RBBIStateTableRow {
/* StatusTable of the set of matching */ /* StatusTable of the set of matching */
/* tags (rule status values) */ /* tags (rule status values) */
int16_t fReserved; int16_t fReserved;
uint16_t fNextState[2]; /* Next State, indexed by char category. */ uint16_t fNextState[1]; /* Next State, indexed by char category. */
/* This array does not have two elements */ /* Variable-length array declared with length 1 */
/* Array Size is actually fData->fHeader->fCatCount */ /* to disable bounds checkers. */
/* Array Size is actually fData->fHeader->fCatCount*/
/* CAUTION: see RBBITableBuilder::getTableSize() */ /* CAUTION: see RBBITableBuilder::getTableSize() */
/* before changing anything here. */ /* before changing anything here. */
}; };
@ -129,7 +130,9 @@ struct RBBIStateTable {
uint32_t fRowLen; /* Length of a state table row, in bytes. */ uint32_t fRowLen; /* Length of a state table row, in bytes. */
uint32_t fFlags; /* Option Flags for this state table */ uint32_t fFlags; /* Option Flags for this state table */
uint32_t fReserved; /* reserved */ 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 */ /* (making it char[] simplifies ugly address */
/* arithmetic for indexing variable length rows.) */ /* arithmetic for indexing variable length rows.) */
}; };

View File

@ -1095,15 +1095,12 @@ int32_t RBBITableBuilder::getTableSize() const {
return 0; 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(); numRows = fDStates->size();
numCols = fRB->fSetBuilder->getNumCharCategories(); numCols = fRB->fSetBuilder->getNumCharCategories();
// Note The declaration of RBBIStateTableRow is for a table of two columns. rowSize = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t)*numCols;
// 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);
size += numRows * rowSize; size += numRows * rowSize;
return size; return size;
} }
@ -1126,14 +1123,14 @@ void RBBITableBuilder::exportTable(void *where) {
return; return;
} }
if (fRB->fSetBuilder->getNumCharCategories() > 0x7fff || int32_t catCount = fRB->fSetBuilder->getNumCharCategories();
if (catCount > 0x7fff ||
fDStates->size() > 0x7fff) { fDStates->size() > 0x7fff) {
*fStatus = U_BRK_INTERNAL_ERROR; *fStatus = U_BRK_INTERNAL_ERROR;
return; return;
} }
table->fRowLen = sizeof(RBBIStateTableRow) + table->fRowLen = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t) * catCount;
sizeof(uint16_t) * (fRB->fSetBuilder->getNumCharCategories() - 2);
table->fNumStates = fDStates->size(); table->fNumStates = fDStates->size();
table->fFlags = 0; table->fFlags = 0;
if (fRB->fLookAheadHardBreak) { if (fRB->fLookAheadHardBreak) {
@ -1152,7 +1149,7 @@ void RBBITableBuilder::exportTable(void *where) {
row->fAccepting = (int16_t)sd->fAccepting; row->fAccepting = (int16_t)sd->fAccepting;
row->fLookAhead = (int16_t)sd->fLookAhead; row->fLookAhead = (int16_t)sd->fLookAhead;
row->fTagIdx = (int16_t)sd->fTagsIdx; 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); row->fNextState[col] = (uint16_t)sd->fDtran->elementAti(col);
} }
} }

View File

@ -77,7 +77,11 @@ typedef struct {
typedef struct { typedef struct {
uint32_t count; uint32_t count;
uint32_t reserved; 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; } PointerTOC;

View File

@ -52,7 +52,11 @@ typedef struct {
typedef struct { typedef struct {
uint32_t count; 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; } UDataOffsetTOC;
/** /**

View File

@ -50,10 +50,12 @@ static void syntaxError(const UnicodeString& pattern,
parseError.preContext[stop-start] = 0; parseError.preContext[stop-start] = 0;
//for post-context //for post-context
start = pos+1; start = pattern.moveIndex32(pos, 1);
stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEXT_LEN-1)) : stop = pos + U_PARSE_CONTEXT_LEN - 1;
pattern.length(); if (stop > pattern.length()) {
pattern.extract(start,stop-start,parseError.postContext,0); stop = pattern.length();
}
pattern.extract(start, stop - start, parseError.postContext, 0);
//null terminate the buffer //null terminate the buffer
parseError.postContext[stop-start]= 0; parseError.postContext[stop-start]= 0;
} }