LCOV - code coverage report
Current view: top level - gfx/ots/src - cff.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 551 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012 The Chromium Authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "cff.h"
       6             : 
       7             : #include <cstring>
       8             : #include <utility>
       9             : #include <vector>
      10             : 
      11             : #include "maxp.h"
      12             : #include "cff_type2_charstring.h"
      13             : 
      14             : // CFF - PostScript font program (Compact Font Format) table
      15             : // http://www.microsoft.com/typography/otspec/cff.htm
      16             : // http://www.microsoft.com/typography/otspec/cffspec.htm
      17             : 
      18             : #define TABLE_NAME "CFF"
      19             : 
      20             : namespace {
      21             : 
      22             : enum DICT_OPERAND_TYPE {
      23             :   DICT_OPERAND_INTEGER,
      24             :   DICT_OPERAND_REAL,
      25             :   DICT_OPERATOR,
      26             : };
      27             : 
      28             : enum DICT_DATA_TYPE {
      29             :   DICT_DATA_TOPLEVEL,
      30             :   DICT_DATA_FDARRAY,
      31             : };
      32             : 
      33             : enum FONT_FORMAT {
      34             :   FORMAT_UNKNOWN,
      35             :   FORMAT_CID_KEYED,
      36             :   FORMAT_OTHER,  // Including synthetic fonts
      37             : };
      38             : 
      39             : // see Appendix. A
      40             : const size_t kNStdString = 390;
      41             : 
      42           0 : bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
      43           0 :   if (off_size > 4) {
      44           0 :     return OTS_FAILURE();
      45             :   }
      46             : 
      47           0 :   uint32_t tmp32 = 0;
      48           0 :   for (unsigned i = 0; i < off_size; ++i) {
      49           0 :     uint8_t tmp8 = 0;
      50           0 :     if (!table->ReadU8(&tmp8)) {
      51           0 :       return OTS_FAILURE();
      52             :     }
      53           0 :     tmp32 <<= 8;
      54           0 :     tmp32 += tmp8;
      55             :   }
      56           0 :   *offset = tmp32;
      57           0 :   return true;
      58             : }
      59             : 
      60           0 : bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) {
      61           0 :   index->off_size = 0;
      62           0 :   index->offsets.clear();
      63             : 
      64           0 :   if (!table->ReadU16(&(index->count))) {
      65           0 :     return OTS_FAILURE();
      66             :   }
      67           0 :   if (index->count == 0) {
      68             :     // An empty INDEX.
      69           0 :     index->offset_to_next = table->offset();
      70           0 :     return true;
      71             :   }
      72             : 
      73           0 :   if (!table->ReadU8(&(index->off_size))) {
      74           0 :     return OTS_FAILURE();
      75             :   }
      76           0 :   if ((index->off_size == 0) ||
      77           0 :       (index->off_size > 4)) {
      78           0 :     return OTS_FAILURE();
      79             :   }
      80             : 
      81           0 :   const size_t array_size = (index->count + 1) * index->off_size;
      82             :   // less than ((64k + 1) * 4), thus does not overflow.
      83           0 :   const size_t object_data_offset = table->offset() + array_size;
      84             :   // does not overflow too, since offset() <= 1GB.
      85             : 
      86           0 :   if (object_data_offset >= table->length()) {
      87           0 :     return OTS_FAILURE();
      88             :   }
      89             : 
      90           0 :   for (unsigned i = 0; i <= index->count; ++i) {  // '<=' is not a typo.
      91           0 :     uint32_t rel_offset = 0;
      92           0 :     if (!ReadOffset(table, index->off_size, &rel_offset)) {
      93           0 :       return OTS_FAILURE();
      94             :     }
      95           0 :     if (rel_offset < 1) {
      96           0 :       return OTS_FAILURE();
      97             :     }
      98           0 :     if (i == 0 && rel_offset != 1) {
      99           0 :       return OTS_FAILURE();
     100             :     }
     101             : 
     102           0 :     if (rel_offset > table->length()) {
     103           0 :       return OTS_FAILURE();
     104             :     }
     105             : 
     106             :     // does not underflow.
     107           0 :     if (object_data_offset > table->length() - (rel_offset - 1)) {
     108           0 :       return OTS_FAILURE();
     109             :     }
     110             : 
     111           0 :     index->offsets.push_back(
     112           0 :         object_data_offset + (rel_offset - 1));  // less than length(), 1GB.
     113             :   }
     114             : 
     115           0 :   for (unsigned i = 1; i < index->offsets.size(); ++i) {
     116             :     // We allow consecutive identical offsets here for zero-length strings.
     117             :     // See http://crbug.com/69341 for more details.
     118           0 :     if (index->offsets[i] < index->offsets[i - 1]) {
     119           0 :       return OTS_FAILURE();
     120             :     }
     121             :   }
     122             : 
     123           0 :   index->offset_to_next = index->offsets.back();
     124           0 :   return true;
     125             : }
     126             : 
     127           0 : bool ParseNameData(
     128             :     ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) {
     129           0 :   uint8_t name[256] = {0};
     130           0 :   if (index.offsets.size() == 0) {  // just in case.
     131           0 :     return OTS_FAILURE();
     132             :   }
     133           0 :   for (unsigned i = 1; i < index.offsets.size(); ++i) {
     134           0 :     const size_t length = index.offsets[i] - index.offsets[i - 1];
     135             :     // font names should be no longer than 127 characters.
     136           0 :     if (length > 127) {
     137           0 :       return OTS_FAILURE();
     138             :     }
     139             : 
     140           0 :     table->set_offset(index.offsets[i - 1]);
     141           0 :     if (!table->Read(name, length)) {
     142           0 :       return OTS_FAILURE();
     143             :     }
     144             : 
     145           0 :     for (size_t j = 0; j < length; ++j) {
     146             :       // setting the first byte to NUL is allowed.
     147           0 :       if (j == 0 && name[j] == 0) continue;
     148             :       // non-ASCII characters are not recommended (except the first character).
     149           0 :       if (name[j] < 33 || name[j] > 126) {
     150           0 :         return OTS_FAILURE();
     151             :       }
     152             :       // [, ], ... are not allowed.
     153           0 :       if (std::strchr("[](){}<>/% ", name[j])) {
     154           0 :         return OTS_FAILURE();
     155             :       }
     156             :     }
     157             :   }
     158             : 
     159           0 :   *out_name = reinterpret_cast<char *>(name);
     160           0 :   return true;
     161             : }
     162             : 
     163           0 : bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
     164             :                  size_t table_length) {
     165           0 :   if (operand.second != DICT_OPERAND_INTEGER) {
     166           0 :     return OTS_FAILURE();
     167             :   }
     168           0 :   if (operand.first >= table_length) {
     169           0 :     return OTS_FAILURE();
     170             :   }
     171           0 :   return true;
     172             : }
     173             : 
     174           0 : bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
     175             :               size_t sid_max) {
     176           0 :   if (operand.second != DICT_OPERAND_INTEGER) {
     177           0 :     return OTS_FAILURE();
     178             :   }
     179           0 :   if (operand.first > sid_max) {
     180           0 :     return OTS_FAILURE();
     181             :   }
     182           0 :   return true;
     183             : }
     184             : 
     185           0 : bool ParseDictDataBcd(
     186             :     ots::Buffer *table,
     187             :     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
     188           0 :   bool read_decimal_point = false;
     189           0 :   bool read_e = false;
     190             : 
     191           0 :   uint8_t nibble = 0;
     192           0 :   size_t count = 0;
     193             :   while (true) {
     194           0 :     if (!table->ReadU8(&nibble)) {
     195           0 :       return OTS_FAILURE();
     196             :     }
     197           0 :     if ((nibble & 0xf0) == 0xf0) {
     198           0 :       if ((nibble & 0xf) == 0xf) {
     199             :         // TODO(yusukes): would be better to store actual double value,
     200             :         // rather than the dummy integer.
     201           0 :         operands->push_back(std::make_pair(static_cast<uint32_t>(0),
     202           0 :                                            DICT_OPERAND_REAL));
     203           0 :         return true;
     204             :       }
     205           0 :       return OTS_FAILURE();
     206             :     }
     207           0 :     if ((nibble & 0x0f) == 0x0f) {
     208           0 :       operands->push_back(std::make_pair(static_cast<uint32_t>(0),
     209           0 :                                          DICT_OPERAND_REAL));
     210           0 :       return true;
     211             :     }
     212             : 
     213             :     // check number format
     214             :     uint8_t nibbles[2];
     215           0 :     nibbles[0] = (nibble & 0xf0) >> 8;
     216           0 :     nibbles[1] = (nibble & 0x0f);
     217           0 :     for (unsigned i = 0; i < 2; ++i) {
     218           0 :       if (nibbles[i] == 0xd) {  // reserved number
     219           0 :         return OTS_FAILURE();
     220             :       }
     221           0 :       if ((nibbles[i] == 0xe) &&  // minus
     222           0 :           ((count > 0) || (i > 0))) {
     223           0 :         return OTS_FAILURE();  // minus sign should be the first character.
     224             :       }
     225           0 :       if (nibbles[i] == 0xa) {  // decimal point
     226           0 :         if (!read_decimal_point) {
     227           0 :           read_decimal_point = true;
     228             :         } else {
     229           0 :           return OTS_FAILURE();  // two or more points.
     230             :         }
     231             :       }
     232           0 :       if ((nibbles[i] == 0xb) ||  // E+
     233           0 :           (nibbles[i] == 0xc)) {  // E-
     234           0 :         if (!read_e) {
     235           0 :           read_e = true;
     236             :         } else {
     237           0 :           return OTS_FAILURE();  // two or more E's.
     238             :         }
     239             :       }
     240             :     }
     241           0 :     ++count;
     242           0 :   }
     243             : }
     244             : 
     245           0 : bool ParseDictDataEscapedOperator(
     246             :     ots::Buffer *table,
     247             :     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
     248           0 :   uint8_t op = 0;
     249           0 :   if (!table->ReadU8(&op)) {
     250           0 :     return OTS_FAILURE();
     251             :   }
     252             : 
     253           0 :   if ((op <= 14) ||
     254           0 :       (op >= 17 && op <= 23) ||
     255           0 :       (op >= 30 && op <= 38)) {
     256           0 :     operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR));
     257           0 :     return true;
     258             :   }
     259             : 
     260             :   // reserved area.
     261           0 :   return OTS_FAILURE();
     262             : }
     263             : 
     264           0 : bool ParseDictDataNumber(
     265             :     ots::Buffer *table, uint8_t b0,
     266             :     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
     267           0 :   uint8_t b1 = 0;
     268           0 :   uint8_t b2 = 0;
     269           0 :   uint8_t b3 = 0;
     270           0 :   uint8_t b4 = 0;
     271             : 
     272           0 :   switch (b0) {
     273             :     case 28:  // shortint
     274           0 :       if (!table->ReadU8(&b1) ||
     275           0 :           !table->ReadU8(&b2)) {
     276           0 :         return OTS_FAILURE();
     277             :       }
     278           0 :       operands->push_back(std::make_pair(
     279           0 :           static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
     280           0 :       return true;
     281             : 
     282             :     case 29:  // longint
     283           0 :       if (!table->ReadU8(&b1) ||
     284           0 :           !table->ReadU8(&b2) ||
     285           0 :           !table->ReadU8(&b3) ||
     286           0 :           !table->ReadU8(&b4)) {
     287           0 :         return OTS_FAILURE();
     288             :       }
     289           0 :       operands->push_back(std::make_pair(
     290           0 :           static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4),
     291           0 :           DICT_OPERAND_INTEGER));
     292           0 :       return true;
     293             : 
     294             :     case 30:  // binary coded decimal
     295           0 :       return ParseDictDataBcd(table, operands);
     296             : 
     297             :     default:
     298           0 :       break;
     299             :   }
     300             : 
     301             :   uint32_t result;
     302           0 :   if (b0 >=32 && b0 <=246) {
     303           0 :     result = b0 - 139;
     304           0 :   } else if (b0 >=247 && b0 <= 250) {
     305           0 :     if (!table->ReadU8(&b1)) {
     306           0 :       return OTS_FAILURE();
     307             :     }
     308           0 :     result = (b0 - 247) * 256 + b1 + 108;
     309           0 :   } else if (b0 >= 251 && b0 <= 254) {
     310           0 :     if (!table->ReadU8(&b1)) {
     311           0 :       return OTS_FAILURE();
     312             :     }
     313           0 :     result = -(b0 - 251) * 256 + b1 - 108;
     314             :   } else {
     315           0 :     return OTS_FAILURE();
     316             :   }
     317             : 
     318           0 :   operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER));
     319           0 :   return true;
     320             : }
     321             : 
     322           0 : bool ParseDictDataReadNext(
     323             :     ots::Buffer *table,
     324             :     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
     325           0 :   uint8_t op = 0;
     326           0 :   if (!table->ReadU8(&op)) {
     327           0 :     return OTS_FAILURE();
     328             :   }
     329           0 :   if (op <= 21) {
     330           0 :     if (op == 12) {
     331           0 :       return ParseDictDataEscapedOperator(table, operands);
     332             :     }
     333           0 :     operands->push_back(std::make_pair(
     334           0 :         static_cast<uint32_t>(op), DICT_OPERATOR));
     335           0 :     return true;
     336           0 :   } else if (op <= 27 || op == 31 || op == 255) {
     337             :     // reserved area.
     338           0 :     return OTS_FAILURE();
     339             :   }
     340             : 
     341           0 :   return ParseDictDataNumber(table, op, operands);
     342             : }
     343             : 
     344           0 : bool ParsePrivateDictData(
     345             :     const uint8_t *data,
     346             :     size_t table_length, size_t offset, size_t dict_length,
     347             :     DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
     348           0 :   ots::Buffer table(data + offset, dict_length);
     349           0 :   std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
     350             : 
     351             :   // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino
     352             :   // Kaku Gothic Std W8), we create an empty Local Subr here to match the size
     353             :   // of FDArray the size of |local_subrs_per_font|.
     354           0 :   if (type == DICT_DATA_FDARRAY) {
     355           0 :     out_cff->local_subrs_per_font.push_back(new ots::CFFIndex);
     356             :   }
     357             : 
     358           0 :   while (table.offset() < dict_length) {
     359           0 :     if (!ParseDictDataReadNext(&table, &operands)) {
     360           0 :       return OTS_FAILURE();
     361             :     }
     362           0 :     if (operands.empty()) {
     363           0 :       return OTS_FAILURE();
     364             :     }
     365           0 :     if (operands.size() > 48) {
     366             :       // An operator may be preceded by up to a maximum of 48 operands.
     367           0 :       return OTS_FAILURE();
     368             :     }
     369           0 :     if (operands.back().second != DICT_OPERATOR) {
     370           0 :       continue;
     371             :     }
     372             : 
     373             :     // got operator
     374           0 :     const uint32_t op = operands.back().first;
     375           0 :     operands.pop_back();
     376             : 
     377           0 :     switch (op) {
     378             :       // hints
     379             :       case 6:  // BlueValues
     380             :       case 7:  // OtherBlues
     381             :       case 8:  // FamilyBlues
     382             :       case 9:  // FamilyOtherBlues
     383           0 :         if (operands.empty() || (operands.size() % 2) != 0) {
     384           0 :           return OTS_FAILURE();
     385             :         }
     386           0 :         break;
     387             : 
     388             :       // array
     389             :       case (12U << 8) + 12:  // StemSnapH (delta)
     390             :       case (12U << 8) + 13:  // StemSnapV (delta)
     391           0 :         if (operands.empty()) {
     392           0 :           return OTS_FAILURE();
     393             :         }
     394           0 :         break;
     395             : 
     396             :       // number
     397             :       case 10:  // StdHW
     398             :       case 11:  // StdVW
     399             :       case 20:  // defaultWidthX
     400             :       case 21:  // nominalWidthX
     401             :       case (12U << 8) + 9:   // BlueScale
     402             :       case (12U << 8) + 10:  // BlueShift
     403             :       case (12U << 8) + 11:  // BlueFuzz
     404             :       case (12U << 8) + 17:  // LanguageGroup
     405             :       case (12U << 8) + 18:  // ExpansionFactor
     406             :       case (12U << 8) + 19:  // initialRandomSeed
     407           0 :         if (operands.size() != 1) {
     408           0 :           return OTS_FAILURE();
     409             :         }
     410           0 :         break;
     411             : 
     412             :       // Local Subrs INDEX, offset(self)
     413             :       case 19: {
     414           0 :         if (operands.size() != 1) {
     415           0 :           return OTS_FAILURE();
     416             :         }
     417           0 :         if (operands.back().second != DICT_OPERAND_INTEGER) {
     418           0 :           return OTS_FAILURE();
     419             :         }
     420           0 :         if (operands.back().first >= 1024 * 1024 * 1024) {
     421           0 :           return OTS_FAILURE();
     422             :         }
     423           0 :         if (operands.back().first + offset >= table_length) {
     424           0 :           return OTS_FAILURE();
     425             :         }
     426             :         // parse "16. Local Subrs INDEX"
     427           0 :         ots::Buffer cff_table(data, table_length);
     428           0 :         cff_table.set_offset(operands.back().first + offset);
     429           0 :         ots::CFFIndex *local_subrs_index = NULL;
     430           0 :         if (type == DICT_DATA_FDARRAY) {
     431           0 :           if (out_cff->local_subrs_per_font.empty()) {
     432           0 :             return OTS_FAILURE();  // not reached.
     433             :           }
     434           0 :           local_subrs_index = out_cff->local_subrs_per_font.back();
     435             :         } else { // type == DICT_DATA_TOPLEVEL
     436           0 :           if (out_cff->local_subrs) {
     437           0 :             return OTS_FAILURE();  // two or more local_subrs?
     438             :           }
     439           0 :           local_subrs_index = new ots::CFFIndex;
     440           0 :           out_cff->local_subrs = local_subrs_index;
     441             :         }
     442           0 :         if (!ParseIndex(&cff_table, local_subrs_index)) {
     443           0 :           return OTS_FAILURE();
     444             :         }
     445           0 :         break;
     446             :       }
     447             : 
     448             :       // boolean
     449             :       case (12U << 8) + 14:  // ForceBold
     450           0 :         if (operands.size() != 1) {
     451           0 :           return OTS_FAILURE();
     452             :         }
     453           0 :         if (operands.back().second != DICT_OPERAND_INTEGER) {
     454           0 :           return OTS_FAILURE();
     455             :         }
     456           0 :         if (operands.back().first >= 2) {
     457           0 :           return OTS_FAILURE();
     458             :         }
     459           0 :         break;
     460             : 
     461             :       default:
     462           0 :         return OTS_FAILURE();
     463             :     }
     464           0 :     operands.clear();
     465             :   }
     466             : 
     467           0 :   return true;
     468             : }
     469             : 
     470           0 : bool ParseDictData(const uint8_t *data, size_t table_length,
     471             :                    const ots::CFFIndex &index, uint16_t glyphs,
     472             :                    size_t sid_max, DICT_DATA_TYPE type,
     473             :                    ots::OpenTypeCFF *out_cff) {
     474           0 :   for (unsigned i = 1; i < index.offsets.size(); ++i) {
     475           0 :     if (type == DICT_DATA_TOPLEVEL) {
     476           0 :       out_cff->char_strings_array.push_back(new ots::CFFIndex);
     477             :     }
     478           0 :     size_t dict_length = index.offsets[i] - index.offsets[i - 1];
     479           0 :     ots::Buffer table(data + index.offsets[i - 1], dict_length);
     480             : 
     481           0 :     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
     482             : 
     483           0 :     FONT_FORMAT font_format = FORMAT_UNKNOWN;
     484           0 :     bool have_ros = false;
     485           0 :     uint16_t charstring_glyphs = 0;
     486           0 :     size_t charset_offset = 0;
     487             : 
     488           0 :     while (table.offset() < dict_length) {
     489           0 :       if (!ParseDictDataReadNext(&table, &operands)) {
     490           0 :         return OTS_FAILURE();
     491             :       }
     492           0 :       if (operands.empty()) {
     493           0 :         return OTS_FAILURE();
     494             :       }
     495           0 :       if (operands.size() > 48) {
     496             :         // An operator may be preceded by up to a maximum of 48 operands.
     497           0 :         return OTS_FAILURE();
     498             :       }
     499           0 :       if (operands.back().second != DICT_OPERATOR) continue;
     500             : 
     501             :       // got operator
     502           0 :       const uint32_t op = operands.back().first;
     503           0 :       operands.pop_back();
     504             : 
     505           0 :       switch (op) {
     506             :         // SID
     507             :         case 0:   // version
     508             :         case 1:   // Notice
     509             :         case 2:   // Copyright
     510             :         case 3:   // FullName
     511             :         case 4:   // FamilyName
     512             :         case (12U << 8) + 0:   // Copyright
     513             :         case (12U << 8) + 21:  // PostScript
     514             :         case (12U << 8) + 22:  // BaseFontName
     515             :         case (12U << 8) + 38:  // FontName
     516           0 :           if (operands.size() != 1) {
     517           0 :             return OTS_FAILURE();
     518             :           }
     519           0 :           if (!CheckSid(operands.back(), sid_max)) {
     520           0 :             return OTS_FAILURE();
     521             :           }
     522           0 :           break;
     523             : 
     524             :         // array
     525             :         case 5:   // FontBBox
     526             :         case 14:  // XUID
     527             :         case (12U << 8) + 7:   // FontMatrix
     528             :         case (12U << 8) + 23:  // BaseFontBlend (delta)
     529           0 :           if (operands.empty()) {
     530           0 :             return OTS_FAILURE();
     531             :           }
     532           0 :           break;
     533             : 
     534             :         // number
     535             :         case 13:  // UniqueID
     536             :         case (12U << 8) + 2:   // ItalicAngle
     537             :         case (12U << 8) + 3:   // UnderlinePosition
     538             :         case (12U << 8) + 4:   // UnderlineThickness
     539             :         case (12U << 8) + 5:   // PaintType
     540             :         case (12U << 8) + 8:   // StrokeWidth
     541             :         case (12U << 8) + 20:  // SyntheticBase
     542           0 :           if (operands.size() != 1) {
     543           0 :             return OTS_FAILURE();
     544             :           }
     545           0 :           break;
     546             :         case (12U << 8) + 31:  // CIDFontVersion
     547             :         case (12U << 8) + 32:  // CIDFontRevision
     548             :         case (12U << 8) + 33:  // CIDFontType
     549             :         case (12U << 8) + 34:  // CIDCount
     550             :         case (12U << 8) + 35:  // UIDBase
     551           0 :           if (operands.size() != 1) {
     552           0 :             return OTS_FAILURE();
     553             :           }
     554           0 :           if (font_format != FORMAT_CID_KEYED) {
     555           0 :             return OTS_FAILURE();
     556             :           }
     557           0 :           break;
     558             :         case (12U << 8) + 6:   // CharstringType
     559           0 :           if (operands.size() != 1) {
     560           0 :             return OTS_FAILURE();
     561             :           }
     562           0 :           if(operands.back().second != DICT_OPERAND_INTEGER) {
     563           0 :             return OTS_FAILURE();
     564             :           }
     565           0 :           if (operands.back().first != 2) {
     566             :             // We only support the "Type 2 Charstring Format."
     567             :             // TODO(yusukes): Support Type 1 format? Is that still in use?
     568           0 :             return OTS_FAILURE();
     569             :           }
     570           0 :           break;
     571             : 
     572             :         // boolean
     573             :         case (12U << 8) + 1:   // isFixedPitch
     574           0 :           if (operands.size() != 1) {
     575           0 :             return OTS_FAILURE();
     576             :           }
     577           0 :           if (operands.back().second != DICT_OPERAND_INTEGER) {
     578           0 :             return OTS_FAILURE();
     579             :           }
     580           0 :           if (operands.back().first >= 2) {
     581           0 :             return OTS_FAILURE();
     582             :           }
     583           0 :           break;
     584             : 
     585             :         // offset(0)
     586             :         case 15:  // charset
     587           0 :           if (operands.size() != 1) {
     588           0 :             return OTS_FAILURE();
     589             :           }
     590           0 :           if (operands.back().first <= 2) {
     591             :             // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
     592           0 :             break;
     593             :           }
     594           0 :           if (!CheckOffset(operands.back(), table_length)) {
     595           0 :             return OTS_FAILURE();
     596             :           }
     597           0 :           if (charset_offset) {
     598           0 :             return OTS_FAILURE();  // multiple charset tables?
     599             :           }
     600           0 :           charset_offset = operands.back().first;
     601           0 :           break;
     602             : 
     603             :         case 16: {  // Encoding
     604           0 :           if (operands.size() != 1) {
     605           0 :             return OTS_FAILURE();
     606             :           }
     607           0 :           if (operands.back().first <= 1) {
     608           0 :             break;  // predefined encoding, "Standard" or "Expert", is used.
     609             :           }
     610           0 :           if (!CheckOffset(operands.back(), table_length)) {
     611           0 :             return OTS_FAILURE();
     612             :           }
     613             : 
     614             :           // parse sub dictionary INDEX.
     615           0 :           ots::Buffer cff_table(data, table_length);
     616           0 :           cff_table.set_offset(operands.back().first);
     617           0 :           uint8_t format = 0;
     618           0 :           if (!cff_table.ReadU8(&format)) {
     619           0 :             return OTS_FAILURE();
     620             :           }
     621           0 :           if (format & 0x80) {
     622             :             // supplemental encoding is not supported at the moment.
     623           0 :             return OTS_FAILURE();
     624             :           }
     625             :           // TODO(yusukes): support & parse supplemental encoding tables.
     626           0 :           break;
     627             :         }
     628             : 
     629             :         case 17: {  // CharStrings
     630           0 :           if (type != DICT_DATA_TOPLEVEL) {
     631           0 :             return OTS_FAILURE();
     632             :           }
     633           0 :           if (operands.size() != 1) {
     634           0 :             return OTS_FAILURE();
     635             :           }
     636           0 :           if (!CheckOffset(operands.back(), table_length)) {
     637           0 :             return OTS_FAILURE();
     638             :           }
     639             :           // parse "14. CharStrings INDEX"
     640           0 :           ots::Buffer cff_table(data, table_length);
     641           0 :           cff_table.set_offset(operands.back().first);
     642           0 :           ots::CFFIndex *charstring_index = out_cff->char_strings_array.back();
     643           0 :           if (!ParseIndex(&cff_table, charstring_index)) {
     644           0 :             return OTS_FAILURE();
     645             :           }
     646           0 :           if (charstring_index->count < 2) {
     647           0 :             return OTS_FAILURE();
     648             :           }
     649           0 :           if (charstring_glyphs) {
     650           0 :             return OTS_FAILURE();  // multiple charstring tables?
     651             :           }
     652           0 :           charstring_glyphs = charstring_index->count;
     653           0 :           if (charstring_glyphs != glyphs) {
     654           0 :             return OTS_FAILURE();  // CFF and maxp have different number of glyphs?
     655             :           }
     656           0 :           break;
     657             :         }
     658             : 
     659             :         case (12U << 8) + 36: {  // FDArray
     660           0 :           if (type != DICT_DATA_TOPLEVEL) {
     661           0 :             return OTS_FAILURE();
     662             :           }
     663           0 :           if (operands.size() != 1) {
     664           0 :             return OTS_FAILURE();
     665             :           }
     666           0 :           if (!CheckOffset(operands.back(), table_length)) {
     667           0 :             return OTS_FAILURE();
     668             :           }
     669             : 
     670             :           // parse sub dictionary INDEX.
     671           0 :           ots::Buffer cff_table(data, table_length);
     672           0 :           cff_table.set_offset(operands.back().first);
     673           0 :           ots::CFFIndex sub_dict_index;
     674           0 :           if (!ParseIndex(&cff_table, &sub_dict_index)) {
     675           0 :             return OTS_FAILURE();
     676             :           }
     677           0 :           if (!ParseDictData(data, table_length,
     678             :                              sub_dict_index,
     679             :                              glyphs, sid_max, DICT_DATA_FDARRAY,
     680             :                              out_cff)) {
     681           0 :             return OTS_FAILURE();
     682             :           }
     683           0 :           if (out_cff->font_dict_length != 0) {
     684           0 :             return OTS_FAILURE();  // two or more FDArray found.
     685             :           }
     686           0 :           out_cff->font_dict_length = sub_dict_index.count;
     687           0 :           break;
     688             :         }
     689             : 
     690             :         case (12U << 8) + 37: {  // FDSelect
     691           0 :           if (type != DICT_DATA_TOPLEVEL) {
     692           0 :             return OTS_FAILURE();
     693             :           }
     694           0 :           if (operands.size() != 1) {
     695           0 :             return OTS_FAILURE();
     696             :           }
     697           0 :           if (!CheckOffset(operands.back(), table_length)) {
     698           0 :             return OTS_FAILURE();
     699             :           }
     700             : 
     701             :           // parse FDSelect data structure
     702           0 :           ots::Buffer cff_table(data, table_length);
     703           0 :           cff_table.set_offset(operands.back().first);
     704           0 :           uint8_t format = 0;
     705           0 :           if (!cff_table.ReadU8(&format)) {
     706           0 :             return OTS_FAILURE();
     707             :           }
     708           0 :           if (format == 0) {
     709           0 :             for (uint16_t j = 0; j < glyphs; ++j) {
     710           0 :               uint8_t fd_index = 0;
     711           0 :               if (!cff_table.ReadU8(&fd_index)) {
     712           0 :                 return OTS_FAILURE();
     713             :               }
     714           0 :               (out_cff->fd_select)[j] = fd_index;
     715             :             }
     716           0 :           } else if (format == 3) {
     717           0 :             uint16_t n_ranges = 0;
     718           0 :             if (!cff_table.ReadU16(&n_ranges)) {
     719           0 :               return OTS_FAILURE();
     720             :             }
     721           0 :             if (n_ranges == 0) {
     722           0 :               return OTS_FAILURE();
     723             :             }
     724             : 
     725           0 :             uint16_t last_gid = 0;
     726           0 :             uint8_t fd_index = 0;
     727           0 :             for (unsigned j = 0; j < n_ranges; ++j) {
     728           0 :               uint16_t first = 0;  // GID
     729           0 :               if (!cff_table.ReadU16(&first)) {
     730           0 :                 return OTS_FAILURE();
     731             :               }
     732             : 
     733             :               // Sanity checks.
     734           0 :               if ((j == 0) && (first != 0)) {
     735           0 :                 return OTS_FAILURE();
     736             :               }
     737           0 :               if ((j != 0) && (last_gid >= first)) {
     738           0 :                 return OTS_FAILURE();  // not increasing order.
     739             :               }
     740             : 
     741             :               // Copy the mapping to |out_cff->fd_select|.
     742           0 :               if (j != 0) {
     743           0 :                 for (uint16_t k = last_gid; k < first; ++k) {
     744           0 :                   if (!out_cff->fd_select.insert(
     745           0 :                           std::make_pair(k, fd_index)).second) {
     746           0 :                     return OTS_FAILURE();
     747             :                   }
     748             :                 }
     749             :               }
     750             : 
     751           0 :               if (!cff_table.ReadU8(&fd_index)) {
     752           0 :                 return OTS_FAILURE();
     753             :               }
     754           0 :               last_gid = first;
     755             :               // TODO(yusukes): check GID?
     756             :             }
     757           0 :             uint16_t sentinel = 0;
     758           0 :             if (!cff_table.ReadU16(&sentinel)) {
     759           0 :               return OTS_FAILURE();
     760             :             }
     761           0 :             if (last_gid >= sentinel) {
     762           0 :               return OTS_FAILURE();
     763             :             }
     764           0 :             for (uint16_t k = last_gid; k < sentinel; ++k) {
     765           0 :               if (!out_cff->fd_select.insert(
     766           0 :                       std::make_pair(k, fd_index)).second) {
     767           0 :                 return OTS_FAILURE();
     768             :               }
     769             :             }
     770             :           } else {
     771             :             // unknown format
     772           0 :             return OTS_FAILURE();
     773             :           }
     774           0 :           break;
     775             :         }
     776             : 
     777             :         // Private DICT (2 * number)
     778             :         case 18: {
     779           0 :           if (operands.size() != 2) {
     780           0 :             return OTS_FAILURE();
     781             :           }
     782           0 :           if (operands.back().second != DICT_OPERAND_INTEGER) {
     783           0 :             return OTS_FAILURE();
     784             :           }
     785           0 :           const uint32_t private_offset = operands.back().first;
     786           0 :           operands.pop_back();
     787           0 :           if (operands.back().second != DICT_OPERAND_INTEGER) {
     788           0 :             return OTS_FAILURE();
     789             :           }
     790           0 :           const uint32_t private_length = operands.back().first;
     791           0 :           if (private_offset > table_length) {
     792           0 :             return OTS_FAILURE();
     793             :           }
     794           0 :           if (private_length >= table_length) {
     795           0 :             return OTS_FAILURE();
     796             :           }
     797           0 :           if (private_length + private_offset > table_length) {
     798           0 :             return OTS_FAILURE();
     799             :           }
     800             :           // parse "15. Private DICT Data"
     801           0 :           if (!ParsePrivateDictData(data, table_length,
     802             :                                     private_offset, private_length,
     803             :                                     type, out_cff)) {
     804           0 :             return OTS_FAILURE();
     805             :           }
     806           0 :           break;
     807             :         }
     808             : 
     809             :         // ROS
     810             :         case (12U << 8) + 30:
     811           0 :           if (font_format != FORMAT_UNKNOWN) {
     812           0 :             return OTS_FAILURE();
     813             :           }
     814           0 :           font_format = FORMAT_CID_KEYED;
     815           0 :           if (operands.size() != 3) {
     816           0 :             return OTS_FAILURE();
     817             :           }
     818             :           // check SIDs
     819           0 :           operands.pop_back();  // ignore the first number.
     820           0 :           if (!CheckSid(operands.back(), sid_max)) {
     821           0 :             return OTS_FAILURE();
     822             :           }
     823           0 :           operands.pop_back();
     824           0 :           if (!CheckSid(operands.back(), sid_max)) {
     825           0 :             return OTS_FAILURE();
     826             :           }
     827           0 :           if (have_ros) {
     828           0 :             return OTS_FAILURE();  // multiple ROS tables?
     829             :           }
     830           0 :           have_ros = true;
     831           0 :           break;
     832             : 
     833             :         default:
     834           0 :           return OTS_FAILURE();
     835             :       }
     836           0 :       operands.clear();
     837             : 
     838           0 :       if (font_format == FORMAT_UNKNOWN) {
     839           0 :         font_format = FORMAT_OTHER;
     840             :       }
     841             :     }
     842             : 
     843             :     // parse "13. Charsets"
     844           0 :     if (charset_offset) {
     845           0 :       ots::Buffer cff_table(data, table_length);
     846           0 :       cff_table.set_offset(charset_offset);
     847           0 :       uint8_t format = 0;
     848           0 :       if (!cff_table.ReadU8(&format)) {
     849           0 :         return OTS_FAILURE();
     850             :       }
     851           0 :       switch (format) {
     852             :         case 0:
     853           0 :           for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
     854           0 :             uint16_t sid = 0;
     855           0 :             if (!cff_table.ReadU16(&sid)) {
     856           0 :               return OTS_FAILURE();
     857             :             }
     858           0 :             if (!have_ros && (sid > sid_max)) {
     859           0 :               return OTS_FAILURE();
     860             :             }
     861             :             // TODO(yusukes): check CIDs when have_ros is true.
     862             :           }
     863           0 :           break;
     864             : 
     865             :         case 1:
     866             :         case 2: {
     867           0 :           uint32_t total = 1;  // .notdef is omitted.
     868           0 :           while (total < glyphs) {
     869           0 :             uint16_t sid = 0;
     870           0 :             if (!cff_table.ReadU16(&sid)) {
     871           0 :               return OTS_FAILURE();
     872             :             }
     873           0 :             if (!have_ros && (sid > sid_max)) {
     874           0 :               return OTS_FAILURE();
     875             :             }
     876             :             // TODO(yusukes): check CIDs when have_ros is true.
     877             : 
     878           0 :             if (format == 1) {
     879           0 :               uint8_t left = 0;
     880           0 :               if (!cff_table.ReadU8(&left)) {
     881           0 :                 return OTS_FAILURE();
     882             :               }
     883           0 :               total += (left + 1);
     884             :             } else {
     885           0 :               uint16_t left = 0;
     886           0 :               if (!cff_table.ReadU16(&left)) {
     887           0 :                 return OTS_FAILURE();
     888             :               }
     889           0 :               total += (left + 1);
     890             :             }
     891             :           }
     892           0 :           break;
     893             :         }
     894             : 
     895             :         default:
     896           0 :           return OTS_FAILURE();
     897             :       }
     898             :     }
     899             :   }
     900           0 :   return true;
     901             : }
     902             : 
     903             : }  // namespace
     904             : 
     905             : namespace ots {
     906             : 
     907           0 : bool ots_cff_parse(Font *font, const uint8_t *data, size_t length) {
     908           0 :   Buffer table(data, length);
     909             : 
     910           0 :   font->cff = new OpenTypeCFF;
     911           0 :   font->cff->data = data;
     912           0 :   font->cff->length = length;
     913           0 :   font->cff->font_dict_length = 0;
     914           0 :   font->cff->local_subrs = NULL;
     915             : 
     916             :   // parse "6. Header" in the Adobe Compact Font Format Specification
     917           0 :   uint8_t major = 0;
     918           0 :   uint8_t minor = 0;
     919           0 :   uint8_t hdr_size = 0;
     920           0 :   uint8_t off_size = 0;
     921           0 :   if (!table.ReadU8(&major)) {
     922           0 :     return OTS_FAILURE();
     923             :   }
     924           0 :   if (!table.ReadU8(&minor)) {
     925           0 :     return OTS_FAILURE();
     926             :   }
     927           0 :   if (!table.ReadU8(&hdr_size)) {
     928           0 :     return OTS_FAILURE();
     929             :   }
     930           0 :   if (!table.ReadU8(&off_size)) {
     931           0 :     return OTS_FAILURE();
     932             :   }
     933           0 :   if ((off_size == 0) || (off_size > 4)) {
     934           0 :     return OTS_FAILURE();
     935             :   }
     936             : 
     937           0 :   if ((major != 1) ||
     938           0 :       (minor != 0) ||
     939           0 :       (hdr_size != 4)) {
     940           0 :     return OTS_FAILURE();
     941             :   }
     942           0 :   if (hdr_size >= length) {
     943           0 :     return OTS_FAILURE();
     944             :   }
     945             : 
     946             :   // parse "7. Name INDEX"
     947           0 :   table.set_offset(hdr_size);
     948           0 :   CFFIndex name_index;
     949           0 :   if (!ParseIndex(&table, &name_index)) {
     950           0 :     return OTS_FAILURE();
     951             :   }
     952           0 :   if (!ParseNameData(&table, name_index, &(font->cff->name))) {
     953           0 :     return OTS_FAILURE();
     954             :   }
     955             : 
     956             :   // parse "8. Top DICT INDEX"
     957           0 :   table.set_offset(name_index.offset_to_next);
     958           0 :   CFFIndex top_dict_index;
     959           0 :   if (!ParseIndex(&table, &top_dict_index)) {
     960           0 :     return OTS_FAILURE();
     961             :   }
     962           0 :   if (name_index.count != top_dict_index.count) {
     963           0 :     return OTS_FAILURE();
     964             :   }
     965             : 
     966             :   // parse "10. String INDEX"
     967           0 :   table.set_offset(top_dict_index.offset_to_next);
     968           0 :   CFFIndex string_index;
     969           0 :   if (!ParseIndex(&table, &string_index)) {
     970           0 :     return OTS_FAILURE();
     971             :   }
     972           0 :   if (string_index.count >= 65000 - kNStdString) {
     973           0 :     return OTS_FAILURE();
     974             :   }
     975             : 
     976           0 :   const uint16_t num_glyphs = font->maxp->num_glyphs;
     977           0 :   const size_t sid_max = string_index.count + kNStdString;
     978             :   // string_index.count == 0 is allowed.
     979             : 
     980             :   // parse "9. Top DICT Data"
     981           0 :   if (!ParseDictData(data, length, top_dict_index,
     982             :                      num_glyphs, sid_max,
     983             :                      DICT_DATA_TOPLEVEL, font->cff)) {
     984           0 :     return OTS_FAILURE();
     985             :   }
     986             : 
     987             :   // parse "16. Global Subrs INDEX"
     988           0 :   table.set_offset(string_index.offset_to_next);
     989           0 :   CFFIndex global_subrs_index;
     990           0 :   if (!ParseIndex(&table, &global_subrs_index)) {
     991           0 :     return OTS_FAILURE();
     992             :   }
     993             : 
     994             :   // Check if all fd_index in FDSelect are valid.
     995           0 :   std::map<uint16_t, uint8_t>::const_iterator iter;
     996           0 :   std::map<uint16_t, uint8_t>::const_iterator end = font->cff->fd_select.end();
     997           0 :   for (iter = font->cff->fd_select.begin(); iter != end; ++iter) {
     998           0 :     if (iter->second >= font->cff->font_dict_length) {
     999           0 :       return OTS_FAILURE();
    1000             :     }
    1001             :   }
    1002             : 
    1003             :   // Check if all charstrings (font hinting code for each glyph) are valid.
    1004           0 :   for (size_t i = 0; i < font->cff->char_strings_array.size(); ++i) {
    1005           0 :     if (!ValidateType2CharStringIndex(font,
    1006           0 :                                       *(font->cff->char_strings_array.at(i)),
    1007             :                                       global_subrs_index,
    1008           0 :                                       font->cff->fd_select,
    1009           0 :                                       font->cff->local_subrs_per_font,
    1010           0 :                                       font->cff->local_subrs,
    1011             :                                       &table)) {
    1012           0 :       return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i);
    1013             :     }
    1014             :   }
    1015             : 
    1016           0 :   return true;
    1017             : }
    1018             : 
    1019           0 : bool ots_cff_should_serialise(Font *font) {
    1020           0 :   return font->cff != NULL;
    1021             : }
    1022             : 
    1023           0 : bool ots_cff_serialise(OTSStream *out, Font *font) {
    1024             :   // TODO(yusukes): would be better to transcode the data,
    1025             :   //                rather than simple memcpy.
    1026           0 :   if (!out->Write(font->cff->data, font->cff->length)) {
    1027           0 :     return OTS_FAILURE();
    1028             :   }
    1029           0 :   return true;
    1030             : }
    1031             : 
    1032           0 : void ots_cff_reuse(Font *font, Font *other) {
    1033           0 :   font->cff = other->cff;
    1034           0 :   font->cff_reused = true;
    1035           0 : }
    1036             : 
    1037           0 : void ots_cff_free(Font *font) {
    1038           0 :   if (font->cff) {
    1039           0 :     for (size_t i = 0; i < font->cff->char_strings_array.size(); ++i) {
    1040           0 :       delete (font->cff->char_strings_array)[i];
    1041             :     }
    1042           0 :     for (size_t i = 0; i < font->cff->local_subrs_per_font.size(); ++i) {
    1043           0 :       delete (font->cff->local_subrs_per_font)[i];
    1044             :     }
    1045           0 :     delete font->cff->local_subrs;
    1046           0 :     delete font->cff;
    1047             :   }
    1048           0 : }
    1049             : 
    1050             : }  // namespace ots
    1051             : 
    1052             : #undef TABLE_NAME

Generated by: LCOV version 1.13