LCOV - code coverage report
Current view: directory - gfx/ots/src - layout.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 804 0 0.0 %
Date: 2012-06-02 Functions: 33 0 0.0 %

       1                 : // Copyright (c) 2011 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 "layout.h"
       6                 : 
       7                 : #include <limits>
       8                 : #include <vector>
       9                 : 
      10                 : #include "gdef.h"
      11                 : 
      12                 : // OpenType Layout Common Table Formats
      13                 : // http://www.microsoft.com/typography/otspec/chapter2.htm
      14                 : 
      15                 : namespace {
      16                 : 
      17                 : // The 'DFLT' tag of script table.
      18                 : const uint32_t kScriptTableTagDflt = 0x44464c54;
      19                 : // The value which represents there is no required feature index.
      20                 : const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF;
      21                 : // The lookup flag bit which indicates existence of MarkFilteringSet.
      22                 : const uint16_t kUseMarkFilteringSetBit = 0x0010;
      23                 : // The lookup flags which require GDEF table.
      24                 : const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008;
      25                 : // The mask for MarkAttachmentType.
      26                 : const uint16_t kMarkAttachmentTypeMask = 0xFF00;
      27                 : // The maximum type number of format for device tables.
      28                 : const uint16_t kMaxDeltaFormatType = 3;
      29                 : // The maximum number of class value.
      30                 : const uint16_t kMaxClassDefValue = 0xFFFF;
      31                 : 
      32                 : struct ScriptRecord {
      33                 :   uint32_t tag;
      34                 :   uint16_t offset;
      35                 : };
      36                 : 
      37                 : struct LangSysRecord {
      38                 :   uint32_t tag;
      39                 :   uint16_t offset;
      40                 : };
      41                 : 
      42                 : struct FeatureRecord {
      43                 :   uint32_t tag;
      44                 :   uint16_t offset;
      45                 : };
      46                 : 
      47               0 : bool ParseLangSysTable(ots::Buffer *subtable, const uint32_t tag,
      48                 :                        const uint16_t num_features) {
      49               0 :   uint16_t offset_lookup_order = 0;
      50               0 :   uint16_t req_feature_index = 0;
      51               0 :   uint16_t feature_count = 0;
      52               0 :   if (!subtable->ReadU16(&offset_lookup_order) ||
      53               0 :       !subtable->ReadU16(&req_feature_index) ||
      54               0 :       !subtable->ReadU16(&feature_count)) {
      55               0 :     return OTS_FAILURE();
      56                 :   }
      57                 :   // |offset_lookup_order| is reserved and should be NULL.
      58               0 :   if (offset_lookup_order != 0) {
      59               0 :     return OTS_FAILURE();
      60                 :   }
      61               0 :   if (req_feature_index != kNoRequiredFeatureIndexDefined &&
      62                 :       req_feature_index >= num_features) {
      63               0 :     return OTS_FAILURE();
      64                 :   }
      65               0 :   if (feature_count > num_features) {
      66               0 :     return OTS_FAILURE();
      67                 :   }
      68                 : 
      69               0 :   for (unsigned i = 0; i < feature_count; ++i) {
      70               0 :     uint16_t feature_index = 0;
      71               0 :     if (!subtable->ReadU16(&feature_index)) {
      72               0 :       return OTS_FAILURE();
      73                 :     }
      74               0 :     if (feature_index >= num_features) {
      75               0 :       return OTS_FAILURE();
      76                 :     }
      77                 :   }
      78               0 :   return true;
      79                 : }
      80                 : 
      81               0 : bool ParseScriptTable(const uint8_t *data, const size_t length,
      82                 :                       const uint32_t tag, const uint16_t num_features) {
      83               0 :   ots::Buffer subtable(data, length);
      84                 : 
      85               0 :   uint16_t offset_default_lang_sys = 0;
      86               0 :   uint16_t lang_sys_count = 0;
      87               0 :   if (!subtable.ReadU16(&offset_default_lang_sys) ||
      88               0 :       !subtable.ReadU16(&lang_sys_count)) {
      89               0 :     return OTS_FAILURE();
      90                 :   }
      91                 : 
      92                 :   // The spec requires a script table for 'DFLT' tag must contain non-NULL
      93                 :   // |offset_default_lang_sys| and |lang_sys_count| == 0
      94               0 :   if (tag == kScriptTableTagDflt &&
      95                 :       (offset_default_lang_sys == 0 || lang_sys_count != 0)) {
      96                 :     OTS_WARNING("DFLT table doesn't satisfy the spec.");
      97               0 :     return OTS_FAILURE();
      98                 :   }
      99                 : 
     100                 :   const unsigned lang_sys_record_end =
     101               0 :       6 * static_cast<unsigned>(lang_sys_count) + 4;
     102               0 :   if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
     103               0 :     return OTS_FAILURE();
     104                 :   }
     105                 : 
     106               0 :   std::vector<LangSysRecord> lang_sys_records;
     107               0 :   lang_sys_records.resize(lang_sys_count);
     108               0 :   uint32_t last_tag = 0;
     109               0 :   for (unsigned i = 0; i < lang_sys_count; ++i) {
     110               0 :     if (!subtable.ReadU32(&lang_sys_records[i].tag) ||
     111               0 :         !subtable.ReadU16(&lang_sys_records[i].offset)) {
     112               0 :       return OTS_FAILURE();
     113                 :     }
     114                 :     // The record array must store the records alphabetically by tag
     115               0 :     if (last_tag != 0 && last_tag > lang_sys_records[i].tag) {
     116               0 :       return OTS_FAILURE();
     117                 :     }
     118               0 :     if (lang_sys_records[i].offset < lang_sys_record_end ||
     119               0 :         lang_sys_records[i].offset >= length) {
     120                 :       OTS_WARNING("bad offset to lang sys table: %x",
     121                 :                   lang_sys_records[i].offset);
     122               0 :       return OTS_FAILURE();
     123                 :     }
     124               0 :     last_tag = lang_sys_records[i].tag;
     125                 :   }
     126                 : 
     127                 :   // Check lang sys tables
     128               0 :   for (unsigned i = 0; i < lang_sys_count; ++i) {
     129               0 :     subtable.set_offset(lang_sys_records[i].offset);
     130               0 :     if (!ParseLangSysTable(&subtable, lang_sys_records[i].tag, num_features)) {
     131               0 :       return OTS_FAILURE();
     132                 :     }
     133                 :   }
     134                 : 
     135               0 :   return true;
     136                 : }
     137                 : 
     138               0 : bool ParseFeatureTable(const uint8_t *data, const size_t length,
     139                 :                        const uint16_t num_lookups) {
     140               0 :   ots::Buffer subtable(data, length);
     141                 : 
     142               0 :   uint16_t offset_feature_params = 0;
     143               0 :   uint16_t lookup_count = 0;
     144               0 :   if (!subtable.ReadU16(&offset_feature_params) ||
     145               0 :       !subtable.ReadU16(&lookup_count)) {
     146               0 :     return OTS_FAILURE();
     147                 :   }
     148                 : 
     149                 :   const unsigned feature_table_end =
     150               0 :       2 * static_cast<unsigned>(lookup_count) + 4;
     151               0 :   if (feature_table_end > std::numeric_limits<uint16_t>::max()) {
     152               0 :     return OTS_FAILURE();
     153                 :   }
     154                 :   // |offset_feature_params| is generally set to NULL.
     155               0 :   if (offset_feature_params != 0 &&
     156                 :       (offset_feature_params < feature_table_end ||
     157                 :        offset_feature_params >= length)) {
     158               0 :     return OTS_FAILURE();
     159                 :   }
     160                 : 
     161               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     162               0 :     uint16_t lookup_index = 0;
     163               0 :     if (!subtable.ReadU16(&lookup_index)) {
     164               0 :       return OTS_FAILURE();
     165                 :     }
     166                 :     // lookup index starts with 0.
     167               0 :     if (lookup_index >= num_lookups) {
     168               0 :       return OTS_FAILURE();
     169                 :     }
     170                 :   }
     171               0 :   return true;
     172                 : }
     173                 : 
     174               0 : bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data,
     175                 :                       const size_t length,
     176                 :                       const ots::LookupSubtableParser* parser) {
     177               0 :   ots::Buffer subtable(data, length);
     178                 : 
     179               0 :   uint16_t lookup_type = 0;
     180               0 :   uint16_t lookup_flag = 0;
     181               0 :   uint16_t subtable_count = 0;
     182               0 :   if (!subtable.ReadU16(&lookup_type) ||
     183               0 :       !subtable.ReadU16(&lookup_flag) ||
     184               0 :       !subtable.ReadU16(&subtable_count)) {
     185               0 :     return OTS_FAILURE();
     186                 :   }
     187                 : 
     188               0 :   if (lookup_type == 0 || lookup_type > parser->num_types) {
     189               0 :     return OTS_FAILURE();
     190                 :   }
     191                 : 
     192                 :   // Check lookup flags.
     193               0 :   if ((lookup_flag & kGdefRequiredFlags) &&
     194               0 :       (!file->gdef || !file->gdef->has_glyph_class_def)) {
     195               0 :     return OTS_FAILURE();
     196                 :   }
     197               0 :   if ((lookup_flag & kMarkAttachmentTypeMask) &&
     198               0 :       (!file->gdef || !file->gdef->has_mark_attachment_class_def)) {
     199               0 :     return OTS_FAILURE();
     200                 :   }
     201               0 :   bool use_mark_filtering_set = false;
     202               0 :   if (lookup_flag & kUseMarkFilteringSetBit) {
     203               0 :     if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) {
     204               0 :       return OTS_FAILURE();
     205                 :     }
     206               0 :     use_mark_filtering_set = true;
     207                 :   }
     208                 : 
     209               0 :   std::vector<uint16_t> subtables;
     210               0 :   subtables.reserve(subtable_count);
     211                 :   // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
     212                 :   // extra 2 bytes will follow after subtable offset array.
     213                 :   const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) +
     214               0 :       (use_mark_filtering_set ? 8 : 6);
     215               0 :   if (lookup_table_end > std::numeric_limits<uint16_t>::max()) {
     216               0 :     return OTS_FAILURE();
     217                 :   }
     218               0 :   for (unsigned i = 0; i < subtable_count; ++i) {
     219               0 :     uint16_t offset_subtable = 0;
     220               0 :     if (!subtable.ReadU16(&offset_subtable)) {
     221               0 :       return OTS_FAILURE();
     222                 :     }
     223               0 :     if (offset_subtable < lookup_table_end ||
     224                 :         offset_subtable >= length) {
     225               0 :       return OTS_FAILURE();
     226                 :     }
     227               0 :     subtables.push_back(offset_subtable);
     228                 :   }
     229               0 :   if (subtables.size() != subtable_count) {
     230               0 :     return OTS_FAILURE();
     231                 :   }
     232                 : 
     233               0 :   if (use_mark_filtering_set) {
     234               0 :     uint16_t mark_filtering_set = 0;
     235               0 :     if (!subtable.ReadU16(&mark_filtering_set)) {
     236               0 :       return OTS_FAILURE();
     237                 :     }
     238               0 :     if (file->gdef->num_mark_glyph_sets == 0 ||
     239                 :         mark_filtering_set >= file->gdef->num_mark_glyph_sets) {
     240               0 :       return OTS_FAILURE();
     241                 :     }
     242                 :   }
     243                 : 
     244                 :   // Parse lookup subtables for this lookup type.
     245               0 :   for (unsigned i = 0; i < subtable_count; ++i) {
     246               0 :     if (!parser->Parse(file, data + subtables[i], length - subtables[i],
     247               0 :                        lookup_type)) {
     248               0 :       return OTS_FAILURE();
     249                 :     }
     250                 :   }
     251               0 :   return true;
     252                 : }
     253                 : 
     254               0 : bool ParseClassDefFormat1(const uint8_t *data, size_t length,
     255                 :                           const uint16_t num_glyphs,
     256                 :                           const uint16_t num_classes) {
     257               0 :   ots::Buffer subtable(data, length);
     258                 : 
     259                 :   // Skip format field.
     260               0 :   if (!subtable.Skip(2)) {
     261               0 :     return OTS_FAILURE();
     262                 :   }
     263                 : 
     264               0 :   uint16_t start_glyph = 0;
     265               0 :   if (!subtable.ReadU16(&start_glyph)) {
     266               0 :     return OTS_FAILURE();
     267                 :   }
     268               0 :   if (start_glyph > num_glyphs) {
     269                 :     OTS_WARNING("bad start glyph ID: %u", start_glyph);
     270               0 :     return OTS_FAILURE();
     271                 :   }
     272                 : 
     273               0 :   uint16_t glyph_count = 0;
     274               0 :   if (!subtable.ReadU16(&glyph_count)) {
     275               0 :     return OTS_FAILURE();
     276                 :   }
     277               0 :   if (glyph_count > num_glyphs) {
     278                 :     OTS_WARNING("bad glyph count: %u", glyph_count);
     279               0 :     return OTS_FAILURE();
     280                 :   }
     281               0 :   for (unsigned i = 0; i < glyph_count; ++i) {
     282               0 :     uint16_t class_value = 0;
     283               0 :     if (!subtable.ReadU16(&class_value)) {
     284               0 :       return OTS_FAILURE();
     285                 :     }
     286               0 :     if (class_value > num_classes) {
     287                 :       OTS_WARNING("bad class value: %u", class_value);
     288               0 :       return OTS_FAILURE();
     289                 :     }
     290                 :   }
     291                 : 
     292               0 :   return true;
     293                 : }
     294                 : 
     295               0 : bool ParseClassDefFormat2(const uint8_t *data, size_t length,
     296                 :                           const uint16_t num_glyphs,
     297                 :                           const uint16_t num_classes) {
     298               0 :   ots::Buffer subtable(data, length);
     299                 : 
     300                 :   // Skip format field.
     301               0 :   if (!subtable.Skip(2)) {
     302               0 :     return OTS_FAILURE();
     303                 :   }
     304                 : 
     305               0 :   uint16_t range_count = 0;
     306               0 :   if (!subtable.ReadU16(&range_count)) {
     307               0 :     return OTS_FAILURE();
     308                 :   }
     309               0 :   if (range_count > num_glyphs) {
     310                 :     OTS_WARNING("bad range count: %u", range_count);
     311               0 :     return OTS_FAILURE();
     312                 :   }
     313                 : 
     314               0 :   uint16_t last_end = 0;
     315               0 :   for (unsigned i = 0; i < range_count; ++i) {
     316               0 :     uint16_t start = 0;
     317               0 :     uint16_t end = 0;
     318               0 :     uint16_t class_value = 0;
     319               0 :     if (!subtable.ReadU16(&start) ||
     320               0 :         !subtable.ReadU16(&end) ||
     321               0 :         !subtable.ReadU16(&class_value)) {
     322               0 :       return OTS_FAILURE();
     323                 :     }
     324               0 :     if (start > end || (last_end && start <= last_end)) {
     325                 :       OTS_WARNING("glyph range is overlapping.");
     326               0 :       return OTS_FAILURE();
     327                 :     }
     328               0 :     if (class_value > num_classes) {
     329                 :       OTS_WARNING("bad class value: %u", class_value);
     330               0 :       return OTS_FAILURE();
     331                 :     }
     332               0 :     last_end = end;
     333                 :   }
     334                 : 
     335               0 :   return true;
     336                 : }
     337                 : 
     338               0 : bool ParseCoverageFormat1(const uint8_t *data, size_t length,
     339                 :                           const uint16_t num_glyphs) {
     340               0 :   ots::Buffer subtable(data, length);
     341                 : 
     342                 :   // Skip format field.
     343               0 :   if (!subtable.Skip(2)) {
     344               0 :     return OTS_FAILURE();
     345                 :   }
     346                 : 
     347               0 :   uint16_t glyph_count = 0;
     348               0 :   if (!subtable.ReadU16(&glyph_count)) {
     349               0 :     return OTS_FAILURE();
     350                 :   }
     351               0 :   if (glyph_count > num_glyphs) {
     352                 :     OTS_WARNING("bad glyph count: %u", glyph_count);
     353               0 :     return OTS_FAILURE();
     354                 :   }
     355               0 :   for (unsigned i = 0; i < glyph_count; ++i) {
     356               0 :     uint16_t glyph = 0;
     357               0 :     if (!subtable.ReadU16(&glyph)) {
     358               0 :       return OTS_FAILURE();
     359                 :     }
     360               0 :     if (glyph > num_glyphs) {
     361                 :       OTS_WARNING("bad glyph ID: %u", glyph);
     362               0 :       return OTS_FAILURE();
     363                 :     }
     364                 :   }
     365                 : 
     366               0 :   return true;
     367                 : }
     368                 : 
     369               0 : bool ParseCoverageFormat2(const uint8_t *data, size_t length,
     370                 :                           const uint16_t num_glyphs) {
     371               0 :   ots::Buffer subtable(data, length);
     372                 : 
     373                 :   // Skip format field.
     374               0 :   if (!subtable.Skip(2)) {
     375               0 :     return OTS_FAILURE();
     376                 :   }
     377                 : 
     378               0 :   uint16_t range_count = 0;
     379               0 :   if (!subtable.ReadU16(&range_count)) {
     380               0 :     return OTS_FAILURE();
     381                 :   }
     382               0 :   if (range_count > num_glyphs) {
     383                 :     OTS_WARNING("bad range count: %u", range_count);
     384               0 :     return OTS_FAILURE();
     385                 :   }
     386               0 :   uint16_t last_end = 0;
     387               0 :   uint16_t last_start_coverage_index = 0;
     388               0 :   for (unsigned i = 0; i < range_count; ++i) {
     389               0 :     uint16_t start = 0;
     390               0 :     uint16_t end = 0;
     391               0 :     uint16_t start_coverage_index = 0;
     392               0 :     if (!subtable.ReadU16(&start) ||
     393               0 :         !subtable.ReadU16(&end) ||
     394               0 :         !subtable.ReadU16(&start_coverage_index)) {
     395               0 :       return OTS_FAILURE();
     396                 :     }
     397               0 :     if (start > end || (last_end && start <= last_end)) {
     398                 :       OTS_WARNING("glyph range is overlapping.");
     399               0 :       return OTS_FAILURE();
     400                 :     }
     401               0 :     if (start_coverage_index != last_start_coverage_index) {
     402                 :       OTS_WARNING("bad start coverage index.");
     403               0 :       return OTS_FAILURE();
     404                 :     }
     405               0 :     last_end = end;
     406               0 :     last_start_coverage_index += end - start + 1;
     407                 :   }
     408                 : 
     409               0 :   return true;
     410                 : }
     411                 : 
     412                 : // Parsers for Contextual subtables in GSUB/GPOS tables.
     413                 : 
     414               0 : bool ParseLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs,
     415                 :                        const uint16_t num_lookups) {
     416               0 :   uint16_t sequence_index = 0;
     417               0 :   uint16_t lookup_list_index = 0;
     418               0 :   if (!subtable->ReadU16(&sequence_index) ||
     419               0 :       !subtable->ReadU16(&lookup_list_index)) {
     420               0 :     return OTS_FAILURE();
     421                 :   }
     422               0 :   if (sequence_index >= num_glyphs) {
     423               0 :     return OTS_FAILURE();
     424                 :   }
     425               0 :   if (lookup_list_index >= num_lookups) {
     426               0 :     return OTS_FAILURE();
     427                 :   }
     428               0 :   return true;
     429                 : }
     430                 : 
     431               0 : bool ParseRuleSubtable(const uint8_t *data, const size_t length,
     432                 :                        const uint16_t num_glyphs,
     433                 :                        const uint16_t num_lookups) {
     434               0 :   ots::Buffer subtable(data, length);
     435                 : 
     436               0 :   uint16_t glyph_count = 0;
     437               0 :   uint16_t lookup_count = 0;
     438               0 :   if (!subtable.ReadU16(&glyph_count) ||
     439               0 :       !subtable.ReadU16(&lookup_count)) {
     440               0 :     return OTS_FAILURE();
     441                 :   }
     442                 : 
     443               0 :   if (glyph_count == 0 || glyph_count >= num_glyphs) {
     444               0 :     return OTS_FAILURE();
     445                 :   }
     446               0 :   for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) {
     447               0 :     uint16_t glyph_id = 0;
     448               0 :     if (!subtable.ReadU16(&glyph_id)) {
     449               0 :       return OTS_FAILURE();
     450                 :     }
     451               0 :     if (glyph_id > num_glyphs) {
     452               0 :       return OTS_FAILURE();
     453                 :     }
     454                 :   }
     455                 : 
     456               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     457               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
     458               0 :       return OTS_FAILURE();
     459                 :     }
     460                 :   }
     461               0 :   return true;
     462                 : }
     463                 : 
     464               0 : bool ParseRuleSetTable(const uint8_t *data, const size_t length,
     465                 :                        const uint16_t num_glyphs,
     466                 :                        const uint16_t num_lookups) {
     467               0 :   ots::Buffer subtable(data, length);
     468                 : 
     469               0 :   uint16_t rule_count = 0;
     470               0 :   if (!subtable.ReadU16(&rule_count)) {
     471               0 :     return OTS_FAILURE();
     472                 :   }
     473               0 :   const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2;
     474               0 :   if (rule_end > std::numeric_limits<uint16_t>::max()) {
     475               0 :     return OTS_FAILURE();
     476                 :   }
     477                 : 
     478               0 :   for (unsigned i = 0; i < rule_count; ++i) {
     479               0 :     uint16_t offset_rule = 0;
     480               0 :     if (!subtable.ReadU16(&offset_rule)) {
     481               0 :       return OTS_FAILURE();
     482                 :     }
     483               0 :     if (offset_rule < rule_end || offset_rule >= length) {
     484               0 :       return OTS_FAILURE();
     485                 :     }
     486               0 :     if (!ParseRuleSubtable(data + offset_rule, length - offset_rule,
     487               0 :                            num_glyphs, num_lookups)) {
     488               0 :       return OTS_FAILURE();
     489                 :     }
     490                 :   }
     491                 : 
     492               0 :   return true;
     493                 : }
     494                 : 
     495               0 : bool ParseContextFormat1(const uint8_t *data, const size_t length,
     496                 :                          const uint16_t num_glyphs,
     497                 :                          const uint16_t num_lookups) {
     498               0 :   ots::Buffer subtable(data, length);
     499                 : 
     500               0 :   uint16_t offset_coverage = 0;
     501               0 :   uint16_t rule_set_count = 0;
     502                 :   // Skip format field.
     503               0 :   if (!subtable.Skip(2) ||
     504               0 :       !subtable.ReadU16(&offset_coverage) ||
     505               0 :       !subtable.ReadU16(&rule_set_count)) {
     506               0 :     return OTS_FAILURE();
     507                 :   }
     508                 : 
     509                 :   const unsigned rule_set_end = static_cast<unsigned>(6) +
     510               0 :       rule_set_count * 2;
     511               0 :   if (rule_set_end > std::numeric_limits<uint16_t>::max()) {
     512               0 :     return OTS_FAILURE();
     513                 :   }
     514               0 :   if (offset_coverage < rule_set_end || offset_coverage >= length) {
     515               0 :     return OTS_FAILURE();
     516                 :   }
     517               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
     518               0 :                                length - offset_coverage, num_glyphs)) {
     519               0 :     return OTS_FAILURE();
     520                 :   }
     521                 : 
     522               0 :   for (unsigned i = 0; i < rule_set_count; ++i) {
     523               0 :     uint16_t offset_rule = 0;
     524               0 :     if (!subtable.ReadU16(&offset_rule)) {
     525               0 :       return OTS_FAILURE();
     526                 :     }
     527               0 :     if (offset_rule < rule_set_end || offset_rule >= length) {
     528               0 :       return OTS_FAILURE();
     529                 :     }
     530               0 :     if (!ParseRuleSetTable(data + offset_rule, length - offset_rule,
     531               0 :                            num_glyphs, num_lookups)) {
     532               0 :       return OTS_FAILURE();
     533                 :     }
     534                 :   }
     535                 : 
     536               0 :   return true;
     537                 : }
     538                 : 
     539               0 : bool ParseClassRuleTable(const uint8_t *data, const size_t length,
     540                 :                          const uint16_t num_glyphs,
     541                 :                          const uint16_t num_lookups) {
     542               0 :   ots::Buffer subtable(data, length);
     543                 : 
     544               0 :   uint16_t glyph_count = 0;
     545               0 :   uint16_t lookup_count = 0;
     546               0 :   if (!subtable.ReadU16(&glyph_count) ||
     547               0 :       !subtable.ReadU16(&lookup_count)) {
     548               0 :     return OTS_FAILURE();
     549                 :   }
     550                 : 
     551               0 :   if (glyph_count == 0 || glyph_count >= num_glyphs) {
     552               0 :     return OTS_FAILURE();
     553                 :   }
     554                 : 
     555                 :   // ClassRule table contains an array of classes. Each value of classes
     556                 :   // could take arbitrary values including zero so we don't check these value.
     557               0 :   const unsigned num_classes = glyph_count - static_cast<unsigned>(1);
     558               0 :   if (!subtable.Skip(2 * num_classes)) {
     559               0 :     return OTS_FAILURE();
     560                 :   }
     561                 : 
     562               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     563               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
     564               0 :       return OTS_FAILURE();
     565                 :     }
     566                 :   }
     567               0 :   return true;
     568                 : }
     569                 : 
     570               0 : bool ParseClassSetTable(const uint8_t *data, const size_t length,
     571                 :                         const uint16_t num_glyphs,
     572                 :                         const uint16_t num_lookups) {
     573               0 :   ots::Buffer subtable(data, length);
     574                 : 
     575               0 :   uint16_t class_rule_count = 0;
     576               0 :   if (!subtable.ReadU16(&class_rule_count)) {
     577               0 :     return OTS_FAILURE();
     578                 :   }
     579                 :   const unsigned class_rule_end =
     580               0 :       2 * static_cast<unsigned>(class_rule_count) + 2;
     581               0 :   if (class_rule_end > std::numeric_limits<uint16_t>::max()) {
     582               0 :     return OTS_FAILURE();
     583                 :   }
     584               0 :   for (unsigned i = 0; i < class_rule_count; ++i) {
     585               0 :     uint16_t offset_class_rule = 0;
     586               0 :     if (!subtable.ReadU16(&offset_class_rule)) {
     587               0 :       return OTS_FAILURE();
     588                 :     }
     589               0 :     if (offset_class_rule < class_rule_end || offset_class_rule >= length) {
     590               0 :       return OTS_FAILURE();
     591                 :     }
     592               0 :     if (!ParseClassRuleTable(data + offset_class_rule,
     593                 :                              length - offset_class_rule, num_glyphs,
     594               0 :                              num_lookups)) {
     595               0 :       return OTS_FAILURE();
     596                 :     }
     597                 :   }
     598                 : 
     599               0 :   return true;
     600                 : }
     601                 : 
     602               0 : bool ParseContextFormat2(const uint8_t *data, const size_t length,
     603                 :                             const uint16_t num_glyphs,
     604                 :                             const uint16_t num_lookups) {
     605               0 :   ots::Buffer subtable(data, length);
     606                 : 
     607               0 :   uint16_t offset_coverage = 0;
     608               0 :   uint16_t offset_class_def = 0;
     609               0 :   uint16_t class_set_cnt = 0;
     610                 :   // Skip format field.
     611               0 :   if (!subtable.Skip(2) ||
     612               0 :       !subtable.ReadU16(&offset_coverage) ||
     613               0 :       !subtable.ReadU16(&offset_class_def) ||
     614               0 :       !subtable.ReadU16(&class_set_cnt)) {
     615               0 :     return OTS_FAILURE();
     616                 :   }
     617                 : 
     618               0 :   const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8;
     619               0 :   if (class_set_end > std::numeric_limits<uint16_t>::max()) {
     620               0 :     return OTS_FAILURE();
     621                 :   }
     622               0 :   if (offset_coverage < class_set_end || offset_coverage >= length) {
     623               0 :     return OTS_FAILURE();
     624                 :   }
     625               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
     626               0 :                                length - offset_coverage, num_glyphs)) {
     627               0 :     return OTS_FAILURE();
     628                 :   }
     629                 : 
     630               0 :   if (offset_class_def < class_set_end || offset_class_def >= length) {
     631               0 :     return OTS_FAILURE();
     632                 :   }
     633               0 :   if (!ots::ParseClassDefTable(data + offset_class_def,
     634                 :                                length - offset_class_def,
     635               0 :                                num_glyphs, kMaxClassDefValue)) {
     636               0 :     return OTS_FAILURE();
     637                 :   }
     638                 : 
     639               0 :   for (unsigned i = 0; i < class_set_cnt; ++i) {
     640               0 :     uint16_t offset_class_rule = 0;
     641               0 :     if (!subtable.ReadU16(&offset_class_rule)) {
     642               0 :       return OTS_FAILURE();
     643                 :     }
     644               0 :     if (offset_class_rule) {
     645               0 :       if (offset_class_rule < class_set_end || offset_class_rule >= length) {
     646               0 :         return OTS_FAILURE();
     647                 :       }
     648               0 :       if (!ParseClassSetTable(data + offset_class_rule,
     649                 :                               length - offset_class_rule, num_glyphs,
     650               0 :                               num_lookups)) {
     651               0 :         return OTS_FAILURE();
     652                 :       }
     653                 :     }
     654                 :   }
     655                 : 
     656               0 :   return true;
     657                 : }
     658                 : 
     659               0 : bool ParseContextFormat3(const uint8_t *data, const size_t length,
     660                 :                          const uint16_t num_glyphs,
     661                 :                          const uint16_t num_lookups) {
     662               0 :   ots::Buffer subtable(data, length);
     663                 : 
     664               0 :   uint16_t glyph_count = 0;
     665               0 :   uint16_t lookup_count = 0;
     666                 :   // Skip format field.
     667               0 :   if (!subtable.Skip(2) ||
     668               0 :       !subtable.ReadU16(&glyph_count) ||
     669               0 :       !subtable.ReadU16(&lookup_count)) {
     670               0 :     return OTS_FAILURE();
     671                 :   }
     672                 : 
     673               0 :   if (glyph_count >= num_glyphs) {
     674               0 :     return OTS_FAILURE();
     675                 :   }
     676                 :   const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) +
     677               0 :       4 * static_cast<unsigned>(lookup_count) + 6;
     678               0 :   if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
     679               0 :     return OTS_FAILURE();
     680                 :   }
     681               0 :   for (unsigned i = 0; i < glyph_count; ++i) {
     682               0 :     uint16_t offset_coverage = 0;
     683               0 :     if (!subtable.ReadU16(&offset_coverage)) {
     684               0 :       return OTS_FAILURE();
     685                 :     }
     686               0 :     if (offset_coverage < lookup_record_end || offset_coverage >= length) {
     687               0 :       return OTS_FAILURE();
     688                 :     }
     689               0 :     if (!ots::ParseCoverageTable(data + offset_coverage,
     690               0 :                                  length - offset_coverage, num_glyphs)) {
     691               0 :       return OTS_FAILURE();
     692                 :     }
     693                 :   }
     694                 : 
     695               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     696               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
     697               0 :       return OTS_FAILURE();
     698                 :     }
     699                 :   }
     700                 : 
     701               0 :   return true;
     702                 : }
     703                 : 
     704                 : // Parsers for Chaning Contextual subtables in GSUB/GPOS tables.
     705                 : 
     706               0 : bool ParseChainRuleSubtable(const uint8_t *data, const size_t length,
     707                 :                             const uint16_t num_glyphs,
     708                 :                             const uint16_t num_lookups) {
     709               0 :   ots::Buffer subtable(data, length);
     710                 : 
     711               0 :   uint16_t backtrack_count = 0;
     712               0 :   if (!subtable.ReadU16(&backtrack_count)) {
     713               0 :     return OTS_FAILURE();
     714                 :   }
     715               0 :   if (backtrack_count >= num_glyphs) {
     716               0 :     return OTS_FAILURE();
     717                 :   }
     718               0 :   for (unsigned i = 0; i < backtrack_count; ++i) {
     719               0 :     uint16_t glyph_id = 0;
     720               0 :     if (!subtable.ReadU16(&glyph_id)) {
     721               0 :       return OTS_FAILURE();
     722                 :     }
     723               0 :     if (glyph_id > num_glyphs) {
     724               0 :       return OTS_FAILURE();
     725                 :     }
     726                 :   }
     727                 : 
     728               0 :   uint16_t input_count = 0;
     729               0 :   if (!subtable.ReadU16(&input_count)) {
     730               0 :     return OTS_FAILURE();
     731                 :   }
     732               0 :   if (input_count == 0 || input_count >= num_glyphs) {
     733               0 :     return OTS_FAILURE();
     734                 :   }
     735               0 :   for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) {
     736               0 :     uint16_t glyph_id = 0;
     737               0 :     if (!subtable.ReadU16(&glyph_id)) {
     738               0 :       return OTS_FAILURE();
     739                 :     }
     740               0 :     if (glyph_id > num_glyphs) {
     741               0 :       return OTS_FAILURE();
     742                 :     }
     743                 :   }
     744                 : 
     745               0 :   uint16_t lookahead_count = 0;
     746               0 :   if (!subtable.ReadU16(&lookahead_count)) {
     747               0 :     return OTS_FAILURE();
     748                 :   }
     749               0 :   if (lookahead_count >= num_glyphs) {
     750               0 :     return OTS_FAILURE();
     751                 :   }
     752               0 :   for (unsigned i = 0; i < lookahead_count; ++i) {
     753               0 :     uint16_t glyph_id = 0;
     754               0 :     if (!subtable.ReadU16(&glyph_id)) {
     755               0 :       return OTS_FAILURE();
     756                 :     }
     757               0 :     if (glyph_id > num_glyphs) {
     758               0 :       return OTS_FAILURE();
     759                 :     }
     760                 :   }
     761                 : 
     762               0 :   uint16_t lookup_count = 0;
     763               0 :   if (!subtable.ReadU16(&lookup_count)) {
     764               0 :     return OTS_FAILURE();
     765                 :   }
     766               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     767               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
     768               0 :       return OTS_FAILURE();
     769                 :     }
     770                 :   }
     771                 : 
     772               0 :   return true;
     773                 : }
     774                 : 
     775               0 : bool ParseChainRuleSetTable(const uint8_t *data, const size_t length,
     776                 :                             const uint16_t num_glyphs,
     777                 :                             const uint16_t num_lookups) {
     778               0 :   ots::Buffer subtable(data, length);
     779                 : 
     780               0 :   uint16_t chain_rule_count = 0;
     781               0 :   if (!subtable.ReadU16(&chain_rule_count)) {
     782               0 :     return OTS_FAILURE();
     783                 :   }
     784                 :   const unsigned chain_rule_end =
     785               0 :       2 * static_cast<unsigned>(chain_rule_count) + 2;
     786               0 :   if (chain_rule_end > std::numeric_limits<uint16_t>::max()) {
     787               0 :     return OTS_FAILURE();
     788                 :   }
     789               0 :   for (unsigned i = 0; i < chain_rule_count; ++i) {
     790               0 :     uint16_t offset_chain_rule = 0;
     791               0 :     if (!subtable.ReadU16(&offset_chain_rule)) {
     792               0 :       return OTS_FAILURE();
     793                 :     }
     794               0 :     if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) {
     795               0 :       return OTS_FAILURE();
     796                 :     }
     797               0 :     if (!ParseChainRuleSubtable(data + offset_chain_rule,
     798                 :                                 length - offset_chain_rule,
     799               0 :                                 num_glyphs, num_lookups)) {
     800               0 :       return OTS_FAILURE();
     801                 :     }
     802                 :   }
     803                 : 
     804               0 :   return true;
     805                 : }
     806                 : 
     807               0 : bool ParseChainContextFormat1(const uint8_t *data, const size_t length,
     808                 :                               const uint16_t num_glyphs,
     809                 :                               const uint16_t num_lookups) {
     810               0 :   ots::Buffer subtable(data, length);
     811                 : 
     812               0 :   uint16_t offset_coverage = 0;
     813               0 :   uint16_t chain_rule_set_count = 0;
     814                 :   // Skip format field.
     815               0 :   if (!subtable.Skip(2) ||
     816               0 :       !subtable.ReadU16(&offset_coverage) ||
     817               0 :       !subtable.ReadU16(&chain_rule_set_count)) {
     818               0 :     return OTS_FAILURE();
     819                 :   }
     820                 : 
     821                 :   const unsigned chain_rule_set_end =
     822               0 :       2 * static_cast<unsigned>(chain_rule_set_count) + 6;
     823               0 :   if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) {
     824               0 :     return OTS_FAILURE();
     825                 :   }
     826               0 :   if (offset_coverage < chain_rule_set_end || offset_coverage >= length) {
     827               0 :     return OTS_FAILURE();
     828                 :   }
     829               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
     830               0 :                                length - offset_coverage, num_glyphs)) {
     831               0 :     return OTS_FAILURE();
     832                 :   }
     833                 : 
     834               0 :   for (unsigned i = 0; i < chain_rule_set_count; ++i) {
     835               0 :     uint16_t offset_chain_rule_set = 0;
     836               0 :     if (!subtable.ReadU16(&offset_chain_rule_set)) {
     837               0 :       return OTS_FAILURE();
     838                 :     }
     839               0 :     if (offset_chain_rule_set < chain_rule_set_end ||
     840                 :         offset_chain_rule_set >= length) {
     841               0 :       return OTS_FAILURE();
     842                 :     }
     843               0 :     if (!ParseChainRuleSetTable(data + offset_chain_rule_set,
     844                 :                                    length - offset_chain_rule_set,
     845               0 :                                    num_glyphs, num_lookups)) {
     846               0 :       return OTS_FAILURE();
     847                 :     }
     848                 :   }
     849                 : 
     850               0 :   return true;
     851                 : }
     852                 : 
     853               0 : bool ParseChainClassRuleSubtable(const uint8_t *data, const size_t length,
     854                 :                                  const uint16_t num_glyphs,
     855                 :                                  const uint16_t num_lookups) {
     856               0 :   ots::Buffer subtable(data, length);
     857                 : 
     858                 :   // In this subtable, we don't check the value of classes for now since
     859                 :   // these could take arbitrary values.
     860                 : 
     861               0 :   uint16_t backtrack_count = 0;
     862               0 :   if (!subtable.ReadU16(&backtrack_count)) {
     863               0 :     return OTS_FAILURE();
     864                 :   }
     865               0 :   if (backtrack_count >= num_glyphs) {
     866               0 :     return OTS_FAILURE();
     867                 :   }
     868               0 :   if (!subtable.Skip(2 * backtrack_count)) {
     869               0 :     return OTS_FAILURE();
     870                 :   }
     871                 : 
     872               0 :   uint16_t input_count = 0;
     873               0 :   if (!subtable.ReadU16(&input_count)) {
     874               0 :     return OTS_FAILURE();
     875                 :   }
     876               0 :   if (input_count == 0 || input_count >= num_glyphs) {
     877               0 :     return OTS_FAILURE();
     878                 :   }
     879               0 :   if (!subtable.Skip(2 * (input_count - 1))) {
     880               0 :     return OTS_FAILURE();
     881                 :   }
     882                 : 
     883               0 :   uint16_t lookahead_count = 0;
     884               0 :   if (!subtable.ReadU16(&lookahead_count)) {
     885               0 :     return OTS_FAILURE();
     886                 :   }
     887               0 :   if (lookahead_count >= num_glyphs) {
     888               0 :     return OTS_FAILURE();
     889                 :   }
     890               0 :   if (!subtable.Skip(2 * lookahead_count)) {
     891               0 :     return OTS_FAILURE();
     892                 :   }
     893                 : 
     894               0 :   uint16_t lookup_count = 0;
     895               0 :   if (!subtable.ReadU16(&lookup_count)) {
     896               0 :     return OTS_FAILURE();
     897                 :   }
     898               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
     899               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
     900               0 :       return OTS_FAILURE();
     901                 :     }
     902                 :   }
     903                 : 
     904               0 :   return true;
     905                 : }
     906                 : 
     907               0 : bool ParseChainClassSetTable(const uint8_t *data, const size_t length,
     908                 :                              const uint16_t num_glyphs,
     909                 :                              const uint16_t num_lookups) {
     910               0 :   ots::Buffer subtable(data, length);
     911                 : 
     912               0 :   uint16_t chain_class_rule_count = 0;
     913               0 :   if (!subtable.ReadU16(&chain_class_rule_count)) {
     914               0 :     return OTS_FAILURE();
     915                 :   }
     916                 :   const unsigned chain_class_rule_end =
     917               0 :       2 * static_cast<unsigned>(chain_class_rule_count) + 2;
     918               0 :   if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) {
     919               0 :     return OTS_FAILURE();
     920                 :   }
     921               0 :   for (unsigned i = 0; i < chain_class_rule_count; ++i) {
     922               0 :     uint16_t offset_chain_class_rule = 0;
     923               0 :     if (!subtable.ReadU16(&offset_chain_class_rule)) {
     924               0 :       return OTS_FAILURE();
     925                 :     }
     926               0 :     if (offset_chain_class_rule < chain_class_rule_end ||
     927                 :         offset_chain_class_rule >= length) {
     928               0 :       return OTS_FAILURE();
     929                 :     }
     930               0 :     if (!ParseChainClassRuleSubtable(data + offset_chain_class_rule,
     931                 :                                      length - offset_chain_class_rule,
     932               0 :                                      num_glyphs, num_lookups)) {
     933               0 :       return OTS_FAILURE();
     934                 :     }
     935                 :   }
     936                 : 
     937               0 :   return true;
     938                 : }
     939                 : 
     940               0 : bool ParseChainContextFormat2(const uint8_t *data, const size_t length,
     941                 :                               const uint16_t num_glyphs,
     942                 :                               const uint16_t num_lookups) {
     943               0 :   ots::Buffer subtable(data, length);
     944                 : 
     945               0 :   uint16_t offset_coverage = 0;
     946               0 :   uint16_t offset_backtrack_class_def = 0;
     947               0 :   uint16_t offset_input_class_def = 0;
     948               0 :   uint16_t offset_lookahead_class_def = 0;
     949               0 :   uint16_t chain_class_set_count = 0;
     950                 :   // Skip format field.
     951               0 :   if (!subtable.Skip(2) ||
     952               0 :       !subtable.ReadU16(&offset_coverage) ||
     953               0 :       !subtable.ReadU16(&offset_backtrack_class_def) ||
     954               0 :       !subtable.ReadU16(&offset_input_class_def) ||
     955               0 :       !subtable.ReadU16(&offset_lookahead_class_def) ||
     956               0 :       !subtable.ReadU16(&chain_class_set_count)) {
     957               0 :     return OTS_FAILURE();
     958                 :   }
     959                 : 
     960                 :   const unsigned chain_class_set_end =
     961               0 :       2 * static_cast<unsigned>(chain_class_set_count) + 12;
     962               0 :   if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) {
     963               0 :     return OTS_FAILURE();
     964                 :   }
     965               0 :   if (offset_coverage < chain_class_set_end || offset_coverage >= length) {
     966               0 :     return OTS_FAILURE();
     967                 :   }
     968               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
     969               0 :                                length - offset_coverage, num_glyphs)) {
     970               0 :     return OTS_FAILURE();
     971                 :   }
     972                 : 
     973                 :   // Classes for backtrack/lookahead sequences might not be defined.
     974               0 :   if (offset_backtrack_class_def) {
     975               0 :     if (offset_backtrack_class_def < chain_class_set_end ||
     976                 :         offset_backtrack_class_def >= length) {
     977               0 :       return OTS_FAILURE();
     978                 :     }
     979               0 :     if (!ots::ParseClassDefTable(data + offset_backtrack_class_def,
     980                 :                                  length - offset_backtrack_class_def,
     981               0 :                                  num_glyphs, kMaxClassDefValue)) {
     982               0 :       return OTS_FAILURE();
     983                 :     }
     984                 :   }
     985                 : 
     986               0 :   if (offset_input_class_def < chain_class_set_end ||
     987                 :       offset_input_class_def >= length) {
     988               0 :     return OTS_FAILURE();
     989                 :   }
     990               0 :   if (!ots::ParseClassDefTable(data + offset_input_class_def,
     991                 :                                length - offset_input_class_def,
     992               0 :                                num_glyphs, kMaxClassDefValue)) {
     993               0 :     return OTS_FAILURE();
     994                 :   }
     995                 : 
     996               0 :   if (offset_lookahead_class_def) {
     997               0 :     if (offset_lookahead_class_def < chain_class_set_end ||
     998                 :         offset_lookahead_class_def >= length) {
     999               0 :       return OTS_FAILURE();
    1000                 :     }
    1001               0 :     if (!ots::ParseClassDefTable(data + offset_lookahead_class_def,
    1002                 :                                  length - offset_lookahead_class_def,
    1003               0 :                                  num_glyphs, kMaxClassDefValue)) {
    1004               0 :       return OTS_FAILURE();
    1005                 :     }
    1006                 :   }
    1007                 : 
    1008               0 :   for (unsigned i = 0; i < chain_class_set_count; ++i) {
    1009               0 :     uint16_t offset_chain_class_set = 0;
    1010               0 :     if (!subtable.ReadU16(&offset_chain_class_set)) {
    1011               0 :       return OTS_FAILURE();
    1012                 :     }
    1013                 :     // |offset_chain_class_set| could be NULL.
    1014               0 :     if (offset_chain_class_set) {
    1015               0 :       if (offset_chain_class_set < chain_class_set_end ||
    1016                 :           offset_chain_class_set >= length) {
    1017               0 :         return OTS_FAILURE();
    1018                 :       }
    1019               0 :       if (!ParseChainClassSetTable(data + offset_chain_class_set,
    1020                 :                                    length - offset_chain_class_set,
    1021               0 :                                    num_glyphs, num_lookups)) {
    1022               0 :         return OTS_FAILURE();
    1023                 :       }
    1024                 :     }
    1025                 :   }
    1026                 : 
    1027               0 :   return true;
    1028                 : }
    1029                 : 
    1030               0 : bool ParseChainContextFormat3(const uint8_t *data, const size_t length,
    1031                 :                               const uint16_t num_glyphs,
    1032                 :                               const uint16_t num_lookups) {
    1033               0 :   ots::Buffer subtable(data, length);
    1034                 : 
    1035               0 :   uint16_t backtrack_count = 0;
    1036                 :   // Skip format field.
    1037               0 :   if (!subtable.Skip(2) ||
    1038               0 :       !subtable.ReadU16(&backtrack_count)) {
    1039               0 :     return OTS_FAILURE();
    1040                 :   }
    1041                 : 
    1042               0 :   if (backtrack_count >= num_glyphs) {
    1043               0 :     return OTS_FAILURE();
    1044                 :   }
    1045               0 :   std::vector<uint16_t> offsets_backtrack;
    1046               0 :   offsets_backtrack.reserve(backtrack_count);
    1047               0 :   for (unsigned i = 0; i < backtrack_count; ++i) {
    1048               0 :     uint16_t offset = 0;
    1049               0 :     if (!subtable.ReadU16(&offset)) {
    1050               0 :       return OTS_FAILURE();
    1051                 :     }
    1052               0 :     offsets_backtrack.push_back(offset);
    1053                 :   }
    1054               0 :   if (offsets_backtrack.size() != backtrack_count) {
    1055               0 :     return OTS_FAILURE();
    1056                 :   }
    1057                 : 
    1058               0 :   uint16_t input_count = 0;
    1059               0 :   if (!subtable.ReadU16(&input_count)) {
    1060               0 :     return OTS_FAILURE();
    1061                 :   }
    1062               0 :   if (input_count >= num_glyphs) {
    1063               0 :     return OTS_FAILURE();
    1064                 :   }
    1065               0 :   std::vector<uint16_t> offsets_input;
    1066               0 :   offsets_input.reserve(input_count);
    1067               0 :   for (unsigned i = 0; i < input_count; ++i) {
    1068               0 :     uint16_t offset = 0;
    1069               0 :     if (!subtable.ReadU16(&offset)) {
    1070               0 :       return OTS_FAILURE();
    1071                 :     }
    1072               0 :     offsets_input.push_back(offset);
    1073                 :   }
    1074               0 :   if (offsets_input.size() != input_count) {
    1075               0 :     return OTS_FAILURE();
    1076                 :   }
    1077                 : 
    1078               0 :   uint16_t lookahead_count = 0;
    1079               0 :   if (!subtable.ReadU16(&lookahead_count)) {
    1080               0 :     return OTS_FAILURE();
    1081                 :   }
    1082               0 :   if (lookahead_count >= num_glyphs) {
    1083               0 :     return OTS_FAILURE();
    1084                 :   }
    1085               0 :   std::vector<uint16_t> offsets_lookahead;
    1086               0 :   offsets_lookahead.reserve(lookahead_count);
    1087               0 :   for (unsigned i = 0; i < lookahead_count; ++i) {
    1088               0 :     uint16_t offset = 0;
    1089               0 :     if (!subtable.ReadU16(&offset)) {
    1090               0 :       return OTS_FAILURE();
    1091                 :     }
    1092               0 :     offsets_lookahead.push_back(offset);
    1093                 :   }
    1094               0 :   if (offsets_lookahead.size() != lookahead_count) {
    1095               0 :     return OTS_FAILURE();
    1096                 :   }
    1097                 : 
    1098               0 :   uint16_t lookup_count = 0;
    1099               0 :   if (!subtable.ReadU16(&lookup_count)) {
    1100               0 :     return OTS_FAILURE();
    1101                 :   }
    1102               0 :   for (unsigned i = 0; i < lookup_count; ++i) {
    1103               0 :     if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
    1104               0 :       return OTS_FAILURE();
    1105                 :     }
    1106                 :   }
    1107                 : 
    1108                 :   const unsigned lookup_record_end =
    1109                 :       2 * (static_cast<unsigned>(backtrack_count) +
    1110                 :            static_cast<unsigned>(input_count) +
    1111                 :            static_cast<unsigned>(lookahead_count)) +
    1112               0 :       4 * static_cast<unsigned>(lookup_count) + 10;
    1113               0 :   if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
    1114               0 :     return OTS_FAILURE();
    1115                 :   }
    1116               0 :   for (unsigned i = 0; i < backtrack_count; ++i) {
    1117               0 :     if (offsets_backtrack[i] < lookup_record_end ||
    1118               0 :         offsets_backtrack[i] >= length) {
    1119               0 :       return OTS_FAILURE();
    1120                 :     }
    1121               0 :     if (!ots::ParseCoverageTable(data + offsets_backtrack[i],
    1122               0 :                                  length - offsets_backtrack[i], num_glyphs)) {
    1123               0 :       return OTS_FAILURE();
    1124                 :     }
    1125                 :   }
    1126               0 :   for (unsigned i = 0; i < input_count; ++i) {
    1127               0 :     if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) {
    1128               0 :       return OTS_FAILURE();
    1129                 :     }
    1130               0 :     if (!ots::ParseCoverageTable(data + offsets_input[i],
    1131               0 :                                  length - offsets_input[i], num_glyphs)) {
    1132               0 :       return OTS_FAILURE();
    1133                 :     }
    1134                 :   }
    1135               0 :   for (unsigned i = 0; i < lookahead_count; ++i) {
    1136               0 :     if (offsets_lookahead[i] < lookup_record_end ||
    1137               0 :         offsets_lookahead[i] >= length) {
    1138               0 :       return OTS_FAILURE();
    1139                 :     }
    1140               0 :     if (!ots::ParseCoverageTable(data + offsets_lookahead[i],
    1141               0 :                                  length - offsets_lookahead[i], num_glyphs)) {
    1142               0 :       return OTS_FAILURE();
    1143                 :     }
    1144                 :   }
    1145                 : 
    1146               0 :   return true;
    1147                 : }
    1148                 : 
    1149                 : }  // namespace
    1150                 : 
    1151                 : namespace ots {
    1152                 : 
    1153               0 : bool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data,
    1154                 :                                  const size_t length,
    1155                 :                                  const uint16_t lookup_type) const {
    1156               0 :   for (unsigned i = 0; i < num_types; ++i) {
    1157               0 :     if (parsers[i].type == lookup_type && parsers[i].parse) {
    1158               0 :       if (!parsers[i].parse(file, data, length)) {
    1159               0 :         return OTS_FAILURE();
    1160                 :       }
    1161               0 :       return true;
    1162                 :     }
    1163                 :   }
    1164               0 :   return OTS_FAILURE();
    1165                 : }
    1166                 : 
    1167                 : // Parsing ScriptListTable requires number of features so we need to
    1168                 : // parse FeatureListTable before calling this function.
    1169               0 : bool ParseScriptListTable(const uint8_t *data, const size_t length,
    1170                 :                           const uint16_t num_features) {
    1171               0 :   Buffer subtable(data, length);
    1172                 : 
    1173               0 :   uint16_t script_count = 0;
    1174               0 :   if (!subtable.ReadU16(&script_count)) {
    1175               0 :     return OTS_FAILURE();
    1176                 :   }
    1177                 : 
    1178                 :   const unsigned script_record_end =
    1179               0 :       6 * static_cast<unsigned>(script_count) + 2;
    1180               0 :   if (script_record_end > std::numeric_limits<uint16_t>::max()) {
    1181               0 :     return OTS_FAILURE();
    1182                 :   }
    1183               0 :   std::vector<ScriptRecord> script_list;
    1184               0 :   script_list.reserve(script_count);
    1185               0 :   uint32_t last_tag = 0;
    1186               0 :   for (unsigned i = 0; i < script_count; ++i) {
    1187                 :     ScriptRecord record;
    1188               0 :     if (!subtable.ReadU32(&record.tag) ||
    1189               0 :         !subtable.ReadU16(&record.offset)) {
    1190               0 :       return OTS_FAILURE();
    1191                 :     }
    1192                 :     // Script tags should be arranged alphabetically by tag
    1193               0 :     if (last_tag != 0 && last_tag > record.tag) {
    1194                 :       // Several fonts don't arrange tags alphabetically.
    1195                 :       // It seems that the order of tags might not be a security issue
    1196                 :       // so we just warn it.
    1197                 :       OTS_WARNING("tags aren't arranged alphabetically.");
    1198                 :     }
    1199               0 :     last_tag = record.tag;
    1200               0 :     if (record.offset < script_record_end || record.offset >= length) {
    1201               0 :       return OTS_FAILURE();
    1202                 :     }
    1203               0 :     script_list.push_back(record);
    1204                 :   }
    1205               0 :   if (script_list.size() != script_count) {
    1206               0 :     return OTS_FAILURE();
    1207                 :   }
    1208                 : 
    1209                 :   // Check script records.
    1210               0 :   for (unsigned i = 0; i < script_count; ++i) {
    1211               0 :     if (!ParseScriptTable(data + script_list[i].offset,
    1212               0 :                           length - script_list[i].offset,
    1213               0 :                           script_list[i].tag, num_features)) {
    1214               0 :       return OTS_FAILURE();
    1215                 :     }
    1216                 :   }
    1217                 : 
    1218               0 :   return true;
    1219                 : }
    1220                 : 
    1221                 : // Parsing FeatureListTable requires number of lookups so we need to parse
    1222                 : // LookupListTable before calling this function.
    1223               0 : bool ParseFeatureListTable(const uint8_t *data, const size_t length,
    1224                 :                            const uint16_t num_lookups,
    1225                 :                            uint16_t* num_features) {
    1226               0 :   Buffer subtable(data, length);
    1227                 : 
    1228               0 :   uint16_t feature_count = 0;
    1229               0 :   if (!subtable.ReadU16(&feature_count)) {
    1230               0 :     return OTS_FAILURE();
    1231                 :   }
    1232                 : 
    1233               0 :   std::vector<FeatureRecord> feature_records;
    1234               0 :   feature_records.resize(feature_count);
    1235                 :   const unsigned feature_record_end =
    1236               0 :       6 * static_cast<unsigned>(feature_count) + 2;
    1237               0 :   if (feature_record_end > std::numeric_limits<uint16_t>::max()) {
    1238               0 :     return OTS_FAILURE();
    1239                 :   }
    1240               0 :   uint32_t last_tag = 0;
    1241               0 :   for (unsigned i = 0; i < feature_count; ++i) {
    1242               0 :     if (!subtable.ReadU32(&feature_records[i].tag) ||
    1243               0 :         !subtable.ReadU16(&feature_records[i].offset)) {
    1244               0 :       return OTS_FAILURE();
    1245                 :     }
    1246                 :     // Feature record array should be arranged alphabetically by tag
    1247               0 :     if (last_tag != 0 && last_tag > feature_records[i].tag) {
    1248                 :       // Several fonts don't arrange tags alphabetically.
    1249                 :       // It seems that the order of tags might not be a security issue
    1250                 :       // so we just warn it.
    1251                 :       OTS_WARNING("tags aren't arranged alphabetically.");
    1252                 :     }
    1253               0 :     last_tag = feature_records[i].tag;
    1254               0 :     if (feature_records[i].offset < feature_record_end ||
    1255               0 :         feature_records[i].offset >= length) {
    1256               0 :       return OTS_FAILURE();
    1257                 :     }
    1258                 :   }
    1259                 : 
    1260               0 :   for (unsigned i = 0; i < feature_count; ++i) {
    1261               0 :     if (!ParseFeatureTable(data + feature_records[i].offset,
    1262               0 :                            length - feature_records[i].offset, num_lookups)) {
    1263               0 :       return OTS_FAILURE();
    1264                 :     }
    1265                 :   }
    1266               0 :   *num_features = feature_count;
    1267               0 :   return true;
    1268                 : }
    1269                 : 
    1270                 : // For parsing GPOS/GSUB tables, this function should be called at first to
    1271                 : // obtain the number of lookups because parsing FeatureTableList requires
    1272                 : // the number.
    1273               0 : bool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data,
    1274                 :                           const size_t length,
    1275                 :                           const LookupSubtableParser* parser,
    1276                 :                           uint16_t *num_lookups) {
    1277               0 :   Buffer subtable(data, length);
    1278                 : 
    1279               0 :   if (!subtable.ReadU16(num_lookups)) {
    1280               0 :     return OTS_FAILURE();
    1281                 :   }
    1282                 : 
    1283               0 :   std::vector<uint16_t> lookups;
    1284               0 :   lookups.reserve(*num_lookups);
    1285                 :   const unsigned lookup_end =
    1286               0 :       2 * static_cast<unsigned>(*num_lookups) + 2;
    1287               0 :   if (lookup_end > std::numeric_limits<uint16_t>::max()) {
    1288               0 :     return OTS_FAILURE();
    1289                 :   }
    1290               0 :   for (unsigned i = 0; i < *num_lookups; ++i) {
    1291               0 :     uint16_t offset = 0;
    1292               0 :     if (!subtable.ReadU16(&offset)) {
    1293               0 :       return OTS_FAILURE();
    1294                 :     }
    1295               0 :     if (offset < lookup_end || offset >= length) {
    1296               0 :       return OTS_FAILURE();
    1297                 :     }
    1298               0 :     lookups.push_back(offset);
    1299                 :   }
    1300               0 :   if (lookups.size() != *num_lookups) {
    1301               0 :     return OTS_FAILURE();
    1302                 :   }
    1303                 : 
    1304               0 :   for (unsigned i = 0; i < *num_lookups; ++i) {
    1305               0 :     if (!ParseLookupTable(file, data + lookups[i], length - lookups[i],
    1306               0 :                           parser)) {
    1307               0 :       return OTS_FAILURE();
    1308                 :     }
    1309                 :   }
    1310                 : 
    1311               0 :   return true;
    1312                 : }
    1313                 : 
    1314               0 : bool ParseClassDefTable(const uint8_t *data, size_t length,
    1315                 :                         const uint16_t num_glyphs,
    1316                 :                         const uint16_t num_classes) {
    1317               0 :   Buffer subtable(data, length);
    1318                 : 
    1319               0 :   uint16_t format = 0;
    1320               0 :   if (!subtable.ReadU16(&format)) {
    1321               0 :     return OTS_FAILURE();
    1322                 :   }
    1323               0 :   if (format == 1) {
    1324               0 :     return ParseClassDefFormat1(data, length, num_glyphs, num_classes);
    1325               0 :   } else if (format == 2) {
    1326               0 :     return ParseClassDefFormat2(data, length, num_glyphs, num_classes);
    1327                 :   }
    1328                 : 
    1329               0 :   return OTS_FAILURE();
    1330                 : }
    1331                 : 
    1332               0 : bool ParseCoverageTable(const uint8_t *data, size_t length,
    1333                 :                         const uint16_t num_glyphs) {
    1334               0 :   Buffer subtable(data, length);
    1335                 : 
    1336               0 :   uint16_t format = 0;
    1337               0 :   if (!subtable.ReadU16(&format)) {
    1338               0 :     return OTS_FAILURE();
    1339                 :   }
    1340               0 :   if (format == 1) {
    1341               0 :     return ParseCoverageFormat1(data, length, num_glyphs);
    1342               0 :   } else if (format == 2) {
    1343               0 :     return ParseCoverageFormat2(data, length, num_glyphs);
    1344                 :   }
    1345                 : 
    1346               0 :   return OTS_FAILURE();
    1347                 : }
    1348                 : 
    1349               0 : bool ParseDeviceTable(const uint8_t *data, size_t length) {
    1350               0 :   Buffer subtable(data, length);
    1351                 : 
    1352               0 :   uint16_t start_size = 0;
    1353               0 :   uint16_t end_size = 0;
    1354               0 :   uint16_t delta_format = 0;
    1355               0 :   if (!subtable.ReadU16(&start_size) ||
    1356               0 :       !subtable.ReadU16(&end_size) ||
    1357               0 :       !subtable.ReadU16(&delta_format)) {
    1358               0 :     return OTS_FAILURE();
    1359                 :   }
    1360               0 :   if (start_size > end_size) {
    1361                 :     OTS_WARNING("bad size range: %u > %u", start_size, end_size);
    1362               0 :     return OTS_FAILURE();
    1363                 :   }
    1364               0 :   if (delta_format == 0 || delta_format > kMaxDeltaFormatType) {
    1365                 :     OTS_WARNING("bad delta format: %u", delta_format);
    1366               0 :     return OTS_FAILURE();
    1367                 :   }
    1368                 :   // The number of delta values per uint16. The device table should contain
    1369                 :   // at least |num_units| * 2 bytes compressed data.
    1370                 :   const unsigned num_units = (end_size - start_size) /
    1371               0 :       (1 << (4 - delta_format)) + 1;
    1372                 :   // Just skip |num_units| * 2 bytes since the compressed data could take
    1373                 :   // arbitrary values.
    1374               0 :   if (!subtable.Skip(num_units * 2)) {
    1375               0 :     return OTS_FAILURE();
    1376                 :   }
    1377               0 :   return true;
    1378                 : }
    1379                 : 
    1380               0 : bool ParseContextSubtable(const uint8_t *data, const size_t length,
    1381                 :                           const uint16_t num_glyphs,
    1382                 :                           const uint16_t num_lookups) {
    1383               0 :   Buffer subtable(data, length);
    1384                 : 
    1385               0 :   uint16_t format = 0;
    1386               0 :   if (!subtable.ReadU16(&format)) {
    1387               0 :     return OTS_FAILURE();
    1388                 :   }
    1389                 : 
    1390               0 :   if (format == 1) {
    1391               0 :     if (!ParseContextFormat1(data, length, num_glyphs, num_lookups)) {
    1392               0 :       return OTS_FAILURE();
    1393                 :     }
    1394               0 :   } else if (format == 2) {
    1395               0 :     if (!ParseContextFormat2(data, length, num_glyphs, num_lookups)) {
    1396               0 :       return OTS_FAILURE();
    1397                 :     }
    1398               0 :   } else if (format == 3) {
    1399               0 :     if (!ParseContextFormat3(data, length, num_glyphs, num_lookups)) {
    1400               0 :       return OTS_FAILURE();
    1401                 :     }
    1402                 :   } else {
    1403               0 :     return OTS_FAILURE();
    1404                 :   }
    1405                 : 
    1406               0 :   return true;
    1407                 : }
    1408                 : 
    1409               0 : bool ParseChainingContextSubtable(const uint8_t *data, const size_t length,
    1410                 :                                   const uint16_t num_glyphs,
    1411                 :                                   const uint16_t num_lookups) {
    1412               0 :   Buffer subtable(data, length);
    1413                 : 
    1414               0 :   uint16_t format = 0;
    1415               0 :   if (!subtable.ReadU16(&format)) {
    1416               0 :     return OTS_FAILURE();
    1417                 :   }
    1418                 : 
    1419               0 :   if (format == 1) {
    1420               0 :     if (!ParseChainContextFormat1(data, length, num_glyphs, num_lookups)) {
    1421               0 :       return OTS_FAILURE();
    1422                 :     }
    1423               0 :   } else if (format == 2) {
    1424               0 :     if (!ParseChainContextFormat2(data, length, num_glyphs, num_lookups)) {
    1425               0 :       return OTS_FAILURE();
    1426                 :     }
    1427               0 :   } else if (format == 3) {
    1428               0 :     if (!ParseChainContextFormat3(data, length, num_glyphs, num_lookups)) {
    1429               0 :       return OTS_FAILURE();
    1430                 :     }
    1431                 :   } else {
    1432               0 :     return OTS_FAILURE();
    1433                 :   }
    1434                 : 
    1435               0 :   return true;
    1436                 : }
    1437                 : 
    1438               0 : bool ParseExtensionSubtable(const OpenTypeFile *file,
    1439                 :                             const uint8_t *data, const size_t length,
    1440                 :                             const LookupSubtableParser* parser) {
    1441               0 :   Buffer subtable(data, length);
    1442                 : 
    1443               0 :   uint16_t format = 0;
    1444               0 :   uint16_t lookup_type = 0;
    1445               0 :   uint32_t offset_extension = 0;
    1446               0 :   if (!subtable.ReadU16(&format) ||
    1447               0 :       !subtable.ReadU16(&lookup_type) ||
    1448               0 :       !subtable.ReadU32(&offset_extension)) {
    1449               0 :     return OTS_FAILURE();
    1450                 :   }
    1451                 : 
    1452               0 :   if (format != 1) {
    1453               0 :     return OTS_FAILURE();
    1454                 :   }
    1455                 :   // |lookup_type| should be other than |parser->extension_type|.
    1456               0 :   if (lookup_type < 1 || lookup_type > parser->num_types ||
    1457                 :       lookup_type == parser->extension_type) {
    1458               0 :     return OTS_FAILURE();
    1459                 :   }
    1460                 : 
    1461               0 :   const unsigned format_end = static_cast<unsigned>(8);
    1462               0 :   if (offset_extension < format_end ||
    1463                 :       offset_extension >= length) {
    1464               0 :     return OTS_FAILURE();
    1465                 :   }
    1466                 : 
    1467                 :   // Parse the extension subtable of |lookup_type|.
    1468               0 :   if (!parser->Parse(file, data + offset_extension, length - offset_extension,
    1469               0 :                      lookup_type)) {
    1470               0 :     return OTS_FAILURE();
    1471                 :   }
    1472                 : 
    1473               0 :   return true;
    1474                 : }
    1475                 : 
    1476                 : }  // namespace ots
    1477                 : 

Generated by: LCOV version 1.7