+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
***************************************************************************
-* Copyright (C) 1999-2008 International Business Machines Corporation *
+* Copyright (C) 1999-2014 International Business Machines Corporation *
* and others. All rights reserved. *
***************************************************************************
*/
//
//-----------------------------------------------------------------------------
RBBIDataWrapper::RBBIDataWrapper(const RBBIDataHeader *data, UErrorCode &status) {
+ init0();
init(data, status);
}
RBBIDataWrapper::RBBIDataWrapper(const RBBIDataHeader *data, enum EDontAdopt, UErrorCode &status) {
+ init0();
init(data, status);
fDontFreeData = TRUE;
}
RBBIDataWrapper::RBBIDataWrapper(UDataMemory* udm, UErrorCode &status) {
- const RBBIDataHeader *d = (const RBBIDataHeader *)
- // ((char *)&(udm->pHeader->info) + udm->pHeader->info.size);
- // taking into consideration the padding added in by udata_write
- ((char *)(udm->pHeader) + udm->pHeader->dataHeader.headerSize);
- init(d, status);
+ init0();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ const DataHeader *dh = udm->pHeader;
+ int32_t headerSize = dh->dataHeader.headerSize;
+ if ( !(headerSize >= 20 &&
+ dh->info.isBigEndian == U_IS_BIG_ENDIAN &&
+ dh->info.charsetFamily == U_CHARSET_FAMILY &&
+ dh->info.dataFormat[0] == 0x42 && // dataFormat="Brk "
+ dh->info.dataFormat[1] == 0x72 &&
+ dh->info.dataFormat[2] == 0x6b &&
+ dh->info.dataFormat[3] == 0x20)
+ // Note: info.fFormatVersion is duplicated in the RBBIDataHeader, and is
+ // validated when checking that.
+ ) {
+ status = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ const char *dataAsBytes = reinterpret_cast<const char *>(dh);
+ const RBBIDataHeader *rbbidh = reinterpret_cast<const RBBIDataHeader *>(dataAsBytes + headerSize);
+ init(rbbidh, status);
fUDataMem = udm;
}
// constructors.
//
//-----------------------------------------------------------------------------
+void RBBIDataWrapper::init0() {
+ fHeader = NULL;
+ fForwardTable = NULL;
+ fReverseTable = NULL;
+ fSafeFwdTable = NULL;
+ fSafeRevTable = NULL;
+ fRuleSource = NULL;
+ fRuleStatusTable = NULL;
+ fUDataMem = NULL;
+ fRefCount = 0;
+ fDontFreeData = TRUE;
+}
+
void RBBIDataWrapper::init(const RBBIDataHeader *data, UErrorCode &status) {
if (U_FAILURE(status)) {
return;
}
fHeader = data;
- if (fHeader->fMagic != 0xb1a0 ||
- !(fHeader->fFormatVersion[0] == 3 || // ICU 3.4
- *(int32_t *)fHeader->fFormatVersion == 1)) // ICU 3.2 and earlier.
+ if (fHeader->fMagic != 0xb1a0 || fHeader->fFormatVersion[0] != 3)
{
status = U_INVALID_FORMAT_ERROR;
return;
}
+ // Note: in ICU version 3.2 and earlier, there was a formatVersion 1
+ // that is no longer supported. At that time fFormatVersion was
+ // an int32_t field, rather than an array of 4 bytes.
fDontFreeData = FALSE;
- fUDataMem = NULL;
- fReverseTable = NULL;
- fSafeFwdTable = NULL;
- fSafeRevTable = NULL;
if (data->fFTableLen != 0) {
fForwardTable = (RBBIStateTable *)((char *)data + fHeader->fFTable);
}
//
const uint8_t *inBytes =(const uint8_t *)inData+headerSize;
RBBIDataHeader *rbbiDH = (RBBIDataHeader *)inBytes;
- UBool formatVersionOne = ds->readUInt32(*(int32_t *)rbbiDH->fFormatVersion) == 1;
- if (ds->readUInt32(rbbiDH->fMagic) != 0xb1a0 ||
- !(formatVersionOne || rbbiDH->fFormatVersion[0] == 3) ||
+ if (ds->readUInt32(rbbiDH->fMagic) != 0xb1a0 ||
+ rbbiDH->fFormatVersion[0] != 3 ||
ds->readUInt32(rbbiDH->fLength) < sizeof(RBBIDataHeader))
{
udata_printError(ds, "ubrk_swap(): RBBI Data header is invalid.\n");
outBytes+ds->readUInt32(rbbiDH->fStatusTable), status);
// And, last, the header.
- // For the old version one format, the entire header consists of int32_t values.
- // For the newer formats, the fDataFormat field is an array of four bytes.
- // Swap the whole thing as int32_t, then, for the newer format, re-swap the one field.
+ // It is all int32_t values except for fFormataVersion, which is an array of four bytes.
+ // Swap the whole thing as int32_t, then re-swap the one field.
//
ds->swapArray32(ds, inBytes, sizeof(RBBIDataHeader), outBytes, status);
- if (formatVersionOne == FALSE) {
- ds->swapArray32(ds, outputDH->fFormatVersion, 4, outputDH->fFormatVersion, status);
- }
-
+ ds->swapArray32(ds, outputDH->fFormatVersion, 4, outputDH->fFormatVersion, status);
return totalSize;
}