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
//
// 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 *)

View 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.) */
};

View 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);
}
}

View 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;

View 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;
/**

View 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;
}