]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/rbbidata.cpp
ICU-59131.0.1.tar.gz
[apple/icu.git] / icuSources / common / rbbidata.cpp
index 442fb3d4b1c0671704e62e249d33ff4c1647fb5e..63ed15f39b8c48570787e43d87d448998bea869f 100644 (file)
@@ -1,6 +1,8 @@
+// © 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.                                      *
 ***************************************************************************
 */
@@ -46,20 +48,39 @@ U_NAMESPACE_BEGIN
 //
 //-----------------------------------------------------------------------------
 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;
 }
 
@@ -69,24 +90,34 @@ RBBIDataWrapper::RBBIDataWrapper(UDataMemory* udm, UErrorCode &status) {
 //              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);
     }
@@ -320,9 +351,8 @@ ubrk_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outD
     //
     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");
@@ -433,15 +463,11 @@ ubrk_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outD
                         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;
 }