100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Copyright (c) 2011 The Chromium Authors. All rights reserved.
200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Use of this source code is governed by a BSD-style license that can be
300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// found in the LICENSE file.
400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "layout.h"
600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com#include <limits>
878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com#include <vector>
978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
1078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com#include "gdef.h"
1178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
1200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// OpenType Layout Common Table Formats
1300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// http://www.microsoft.com/typography/otspec/chapter2.htm
1400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comnamespace {
1600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// The 'DFLT' tag of script table.
1878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comconst uint32_t kScriptTableTagDflt = 0x44464c54;
1978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// The value which represents there is no required feature index.
2078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comconst uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF;
2178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// The lookup flag bit which indicates existence of MarkFilteringSet.
2278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comconst uint16_t kUseMarkFilteringSetBit = 0x0010;
23df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org// The lookup flags which require GDEF table.
24df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.orgconst uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008;
2578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// The mask for MarkAttachmentType.
2678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comconst uint16_t kMarkAttachmentTypeMask = 0xFF00;
2778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// The maximum type number of format for device tables.
2878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comconst uint16_t kMaxDeltaFormatType = 3;
29ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org// The maximum number of class value.
30ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgconst uint16_t kMaxClassDefValue = 0xFFFF;
3178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
3278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comstruct ScriptRecord {
3378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t tag;
3478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset;
3578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com};
3678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
3778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comstruct LangSysRecord {
3878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t tag;
3978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset;
4078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com};
4178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
4278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.comstruct FeatureRecord {
4378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t tag;
4478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset;
4578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com};
4678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
4778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseLangSysTable(ots::Buffer *subtable, const uint32_t tag,
4878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                       const uint16_t num_features) {
4978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset_lookup_order = 0;
5078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t req_feature_index = 0;
5178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t feature_count = 0;
5278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable->ReadU16(&offset_lookup_order) ||
5378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable->ReadU16(&req_feature_index) ||
5478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable->ReadU16(&feature_count)) {
5578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
5678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
5778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // |offset_lookup_order| is reserved and should be NULL.
5878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (offset_lookup_order != 0) {
5978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
6078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
6178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (req_feature_index != kNoRequiredFeatureIndexDefined &&
6278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      req_feature_index >= num_features) {
6378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
6478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
6578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (feature_count > num_features) {
6678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
6778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
6878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
6978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < feature_count; ++i) {
7078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    uint16_t feature_index = 0;
7178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!subtable->ReadU16(&feature_index)) {
7278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
7378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
7478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (feature_index >= num_features) {
7578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
7678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
7778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
7878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
7978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
8078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
8178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseScriptTable(const uint8_t *data, const size_t length,
8278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                      const uint32_t tag, const uint16_t num_features) {
8378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  ots::Buffer subtable(data, length);
8478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
8578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset_default_lang_sys = 0;
8678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t lang_sys_count = 0;
8778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&offset_default_lang_sys) ||
8878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&lang_sys_count)) {
8978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
9078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
9178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
9278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // The spec requires a script table for 'DFLT' tag must contain non-NULL
9378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // |offset_default_lang_sys| and |lang_sys_count| == 0
9478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (tag == kScriptTableTagDflt &&
9578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      (offset_default_lang_sys == 0 || lang_sys_count != 0)) {
9678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    OTS_WARNING("DFLT table doesn't satisfy the spec.");
9778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
9878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
9978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
10026afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lang_sys_record_end =
10126afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      6 * static_cast<unsigned>(lang_sys_count) + 4;
10278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
10378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
10478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
10578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
10678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  std::vector<LangSysRecord> lang_sys_records;
10778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  lang_sys_records.resize(lang_sys_count);
10878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t last_tag = 0;
10978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < lang_sys_count; ++i) {
11078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!subtable.ReadU32(&lang_sys_records[i].tag) ||
11178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com        !subtable.ReadU16(&lang_sys_records[i].offset)) {
11278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
11378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
11478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    // The record array must store the records alphabetically by tag
11578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (last_tag != 0 && last_tag > lang_sys_records[i].tag) {
11678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
11778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
11878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (lang_sys_records[i].offset < lang_sys_record_end ||
11978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com        lang_sys_records[i].offset >= length) {
120a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      OTS_WARNING("bad offset to lang sys table: %x",
121a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org                  lang_sys_records[i].offset);
12278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
12378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
12478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    last_tag = lang_sys_records[i].tag;
12578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
12678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
12778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // Check lang sys tables
12878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < lang_sys_count; ++i) {
12978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    subtable.set_offset(lang_sys_records[i].offset);
13078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!ParseLangSysTable(&subtable, lang_sys_records[i].tag, num_features)) {
13178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
13278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
13378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
13478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
13578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
13678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
13778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
13878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseFeatureTable(const uint8_t *data, const size_t length,
13978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                       const uint16_t num_lookups) {
14078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  ots::Buffer subtable(data, length);
14178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
14278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t offset_feature_params = 0;
14378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t lookup_count = 0;
14478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&offset_feature_params) ||
14578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&lookup_count)) {
14678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
14778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
14878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
14926afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned feature_table_end =
15058b44a4cf8d382464149b23b51e400af6114947cbashi@chromium.org      2 * static_cast<unsigned>(lookup_count) + 4;
15178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (feature_table_end > std::numeric_limits<uint16_t>::max()) {
15278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
15378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
15478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // |offset_feature_params| is generally set to NULL.
15578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (offset_feature_params != 0 &&
15678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      (offset_feature_params < feature_table_end ||
15778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com       offset_feature_params >= length)) {
15878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
15978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
16078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
16178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < lookup_count; ++i) {
16278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    uint16_t lookup_index = 0;
16378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!subtable.ReadU16(&lookup_index)) {
16478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
16578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
16678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    // lookup index starts with 0.
16778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (lookup_index >= num_lookups) {
16878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
16978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
17078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
17178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
17278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
17378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
17478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data,
175ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                      const size_t length,
176ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                      const ots::LookupSubtableParser* parser) {
17778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  ots::Buffer subtable(data, length);
17878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
17978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t lookup_type = 0;
18078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t lookup_flag = 0;
18178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t subtable_count = 0;
18278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&lookup_type) ||
18378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&lookup_flag) ||
18478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&subtable_count)) {
18578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
18678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
18778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
188ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookup_type == 0 || lookup_type > parser->num_types) {
18978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
19078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
19178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
19278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // Check lookup flags.
193df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org  if ((lookup_flag & kGdefRequiredFlags) &&
194df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org      (!file->gdef || !file->gdef->has_glyph_class_def)) {
195df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org    return OTS_FAILURE();
196df5b76f08621c6589b4dde7f0b7177bab1bb297cbashi@chromium.org  }
19778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if ((lookup_flag & kMarkAttachmentTypeMask) &&
19878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      (!file->gdef || !file->gdef->has_mark_attachment_class_def)) {
19978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
20078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
20178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  bool use_mark_filtering_set = false;
20278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (lookup_flag & kUseMarkFilteringSetBit) {
20378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) {
20478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
20578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
20678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    use_mark_filtering_set = true;
20778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
20878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
20978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  std::vector<uint16_t> subtables;
21078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  subtables.reserve(subtable_count);
21178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
21278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // extra 2 bytes will follow after subtable offset array.
21326afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lookup_table_end = 2 * static_cast<unsigned>(subtable_count) +
21426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      (use_mark_filtering_set ? 8 : 6);
21578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (lookup_table_end > std::numeric_limits<uint16_t>::max()) {
21678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
21778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
21878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < subtable_count; ++i) {
219e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    uint16_t offset_subtable = 0;
220e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU16(&offset_subtable)) {
22178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
22278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
223e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (offset_subtable < lookup_table_end ||
224e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org        offset_subtable >= length) {
22578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
22678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
227e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    subtables.push_back(offset_subtable);
22878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
2296b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (subtables.size() != subtable_count) {
2306b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
2316b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
23278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
23378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (use_mark_filtering_set) {
23478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    uint16_t mark_filtering_set = 0;
23578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!subtable.ReadU16(&mark_filtering_set)) {
23678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
23778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
23878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (file->gdef->num_mark_glyph_sets == 0 ||
23978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com        mark_filtering_set >= file->gdef->num_mark_glyph_sets) {
24078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
24178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
24278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
24378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
24478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // Parse lookup subtables for this lookup type.
24578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < subtable_count; ++i) {
246ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!parser->Parse(file, data + subtables[i], length - subtables[i],
247ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       lookup_type)) {
24878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
24978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
25078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
25178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
25278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
25378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
25400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseClassDefFormat1(const uint8_t *data, size_t length,
25500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                          const uint16_t num_glyphs,
25600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                          const uint16_t num_classes) {
25700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
25800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
25900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Skip format field.
26000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.Skip(2)) {
26100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
26200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
26300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
26400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t start_glyph = 0;
26500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&start_glyph)) {
26600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
26700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
26800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (start_glyph > num_glyphs) {
26900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad start glyph ID: %u", start_glyph);
27000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
27100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
27200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
27300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t glyph_count = 0;
27400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&glyph_count)) {
27500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
27600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
27700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (glyph_count > num_glyphs) {
27800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad glyph count: %u", glyph_count);
27900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
28000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
28100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < glyph_count; ++i) {
28200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t class_value = 0;
28300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&class_value)) {
28400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
28500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
286ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (class_value > num_classes) {
28700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("bad class value: %u", class_value);
28800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
28900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
29000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
29100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
29200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
29300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
29400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
29500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseClassDefFormat2(const uint8_t *data, size_t length,
29600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                          const uint16_t num_glyphs,
29700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                          const uint16_t num_classes) {
29800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
29900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
30000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Skip format field.
30100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.Skip(2)) {
30200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
30300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
30400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
30500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t range_count = 0;
30600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&range_count)) {
30700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
30800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
30900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (range_count > num_glyphs) {
31000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad range count: %u", range_count);
31100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
31200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
31300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
31400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t last_end = 0;
31500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < range_count; ++i) {
31600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t start = 0;
31700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t end = 0;
31800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t class_value = 0;
31900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&start) ||
32000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        !subtable.ReadU16(&end) ||
32100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        !subtable.ReadU16(&class_value)) {
32200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
32300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
32400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (start > end || (last_end && start <= last_end)) {
32500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("glyph range is overlapping.");
32600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
32700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
328ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (class_value > num_classes) {
32900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("bad class value: %u", class_value);
33000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
33100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
33278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    last_end = end;
33300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
33400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
33500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
33600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
33700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
33800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseCoverageFormat1(const uint8_t *data, size_t length,
339eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                          const uint16_t num_glyphs,
340eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                          const uint16_t expected_num_glyphs) {
34100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
34200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
34300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Skip format field.
34400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.Skip(2)) {
34500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
34600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
34700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
34800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t glyph_count = 0;
34900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&glyph_count)) {
35000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
35100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
35200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (glyph_count > num_glyphs) {
35300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad glyph count: %u", glyph_count);
35400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
35500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
35600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < glyph_count; ++i) {
35700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t glyph = 0;
35800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&glyph)) {
35900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
36000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
36100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (glyph > num_glyphs) {
36200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("bad glyph ID: %u", glyph);
36300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
36400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
36500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
36600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
367eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org  if (expected_num_glyphs && expected_num_glyphs != glyph_count) {
368eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org      OTS_WARNING("unexpected number of glyphs: %u", glyph_count);
369eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org      return OTS_FAILURE();
370eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org  }
371eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org
37200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
37300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
37400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
37500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseCoverageFormat2(const uint8_t *data, size_t length,
376eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                          const uint16_t num_glyphs,
377eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                          const uint16_t expected_num_glyphs) {
37800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ots::Buffer subtable(data, length);
37900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
38000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Skip format field.
38100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.Skip(2)) {
38200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
38300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
38400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
38500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t range_count = 0;
38600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&range_count)) {
38700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
38800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
38978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (range_count > num_glyphs) {
39000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    OTS_WARNING("bad range count: %u", range_count);
39100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
39200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
39300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t last_end = 0;
39478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t last_start_coverage_index = 0;
39500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  for (unsigned i = 0; i < range_count; ++i) {
39600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t start = 0;
39700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t end = 0;
39800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    uint16_t start_coverage_index = 0;
39900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    if (!subtable.ReadU16(&start) ||
40000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        !subtable.ReadU16(&end) ||
40100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        !subtable.ReadU16(&start_coverage_index)) {
40200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
40300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
404006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org
405006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org    // Some of the Adobe Pro fonts have ranges that overlap by one element: the
406006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org    // start of one range is equal to the end of the previous range. Therefore
407006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org    // the < in the following condition should be <= were it not for this.
408006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org    // See crbug.com/134135.
409006c34500789d5bbf2bb077c68381418f25e7e7dagl@chromium.org    if (start > end || (last_end && start < last_end)) {
41000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      OTS_WARNING("glyph range is overlapping.");
41100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      return OTS_FAILURE();
41200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    }
41378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (start_coverage_index != last_start_coverage_index) {
41478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      OTS_WARNING("bad start coverage index.");
41578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
41678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
41778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    last_end = end;
41878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    last_start_coverage_index += end - start + 1;
41900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
42000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
421eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org  if (expected_num_glyphs &&
422eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org      expected_num_glyphs != last_start_coverage_index) {
423eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org      OTS_WARNING("unexpected number of glyphs: %u", last_start_coverage_index);
424eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org      return OTS_FAILURE();
425eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org  }
426eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org
42700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return true;
42800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
42900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
430ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org// Parsers for Contextual subtables in GSUB/GPOS tables.
431ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
432ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs,
433ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       const uint16_t num_lookups) {
434ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t sequence_index = 0;
435ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_list_index = 0;
436ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable->ReadU16(&sequence_index) ||
437ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable->ReadU16(&lookup_list_index)) {
438ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
439ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
440ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (sequence_index >= num_glyphs) {
441ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
442ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
443ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookup_list_index >= num_lookups) {
444ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
445ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
446ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
447ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
448ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
449ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseRuleSubtable(const uint8_t *data, const size_t length,
450ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       const uint16_t num_glyphs,
451ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       const uint16_t num_lookups) {
452ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
453ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
454ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t glyph_count = 0;
455ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
456ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&glyph_count) ||
457ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&lookup_count)) {
458ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
459ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
460ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
461ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (glyph_count == 0 || glyph_count >= num_glyphs) {
462ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
463ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
464ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < glyph_count - static_cast<unsigned>(1); ++i) {
465ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t glyph_id = 0;
466ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&glyph_id)) {
467ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
468ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
469ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (glyph_id > num_glyphs) {
470ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
471ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
472ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
473ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
474ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
475ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
476ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
477ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
478ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
479ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
480ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
481ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
482ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseRuleSetTable(const uint8_t *data, const size_t length,
483ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       const uint16_t num_glyphs,
484ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                       const uint16_t num_lookups) {
485ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
486ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
487ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t rule_count = 0;
488ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&rule_count)) {
489ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
490ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
49126afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned rule_end = 2 * static_cast<unsigned>(rule_count) + 2;
492ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (rule_end > std::numeric_limits<uint16_t>::max()) {
493ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
494ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
495ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
496ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < rule_count; ++i) {
497ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_rule = 0;
498ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_rule)) {
499ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
500ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
501ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_rule < rule_end || offset_rule >= length) {
502ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
503ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
504ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseRuleSubtable(data + offset_rule, length - offset_rule,
505ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                           num_glyphs, num_lookups)) {
506ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
507ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
508ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
509ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
510ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
511ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
512ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
513ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseContextFormat1(const uint8_t *data, const size_t length,
514ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_glyphs,
515ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_lookups) {
516ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
517ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
518ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_coverage = 0;
519ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t rule_set_count = 0;
520ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
521ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
522ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_coverage) ||
523ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&rule_set_count)) {
524ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
525ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
526ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
527ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  const unsigned rule_set_end = static_cast<unsigned>(6) +
528ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      rule_set_count * 2;
529ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (rule_set_end > std::numeric_limits<uint16_t>::max()) {
530ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
531ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
532ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_coverage < rule_set_end || offset_coverage >= length) {
533ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
534ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
535ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseCoverageTable(data + offset_coverage,
536ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_coverage, num_glyphs)) {
537ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
538ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
539ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
540ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < rule_set_count; ++i) {
541ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_rule = 0;
542ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_rule)) {
543ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
544ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
545ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_rule < rule_set_end || offset_rule >= length) {
546ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
547ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
548ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseRuleSetTable(data + offset_rule, length - offset_rule,
549ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                           num_glyphs, num_lookups)) {
550ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
551ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
552ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
553ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
554ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
555ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
556ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
557ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseClassRuleTable(const uint8_t *data, const size_t length,
558ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_glyphs,
559ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_lookups) {
560ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
561ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
562ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t glyph_count = 0;
563ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
564ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&glyph_count) ||
565ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&lookup_count)) {
566ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
567ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
568ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
569ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (glyph_count == 0 || glyph_count >= num_glyphs) {
570ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
571ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
572ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
573ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // ClassRule table contains an array of classes. Each value of classes
574ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // could take arbitrary values including zero so we don't check these value.
575ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  const unsigned num_classes = glyph_count - static_cast<unsigned>(1);
576ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2 * num_classes)) {
577ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
578ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
579ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
580ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
581ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
582ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
583ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
584ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
585ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
586ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
587ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
588ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseClassSetTable(const uint8_t *data, const size_t length,
589ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                        const uint16_t num_glyphs,
590ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                        const uint16_t num_lookups) {
591ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
592ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
593ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t class_rule_count = 0;
594ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&class_rule_count)) {
595ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
596ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
59726afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned class_rule_end =
59826afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(class_rule_count) + 2;
599ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (class_rule_end > std::numeric_limits<uint16_t>::max()) {
600ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
601ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
602ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < class_rule_count; ++i) {
603ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_class_rule = 0;
604ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_class_rule)) {
605ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
606ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
607ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_class_rule < class_rule_end || offset_class_rule >= length) {
608ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
609ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
610ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseClassRuleTable(data + offset_class_rule,
611ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                             length - offset_class_rule, num_glyphs,
612ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                             num_lookups)) {
613ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
614ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
615ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
616ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
617ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
618ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
619ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
620ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseContextFormat2(const uint8_t *data, const size_t length,
621ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_glyphs,
622ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_lookups) {
623ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
624ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
625ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_coverage = 0;
626ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_class_def = 0;
627ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t class_set_cnt = 0;
628ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
629ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
630ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_coverage) ||
631ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_class_def) ||
632ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&class_set_cnt)) {
633ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
634ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
635ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
63626afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned class_set_end = 2 * static_cast<unsigned>(class_set_cnt) + 8;
637ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (class_set_end > std::numeric_limits<uint16_t>::max()) {
638ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
639ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
640ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_coverage < class_set_end || offset_coverage >= length) {
641ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
642ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
643ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseCoverageTable(data + offset_coverage,
644ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_coverage, num_glyphs)) {
645ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
646ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
647ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
648ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_class_def < class_set_end || offset_class_def >= length) {
649ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
650ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
651ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseClassDefTable(data + offset_class_def,
652ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_class_def,
653ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               num_glyphs, kMaxClassDefValue)) {
654ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
655ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
656ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
657ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < class_set_cnt; ++i) {
658ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_class_rule = 0;
659ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_class_rule)) {
660ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
661ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
662ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_class_rule) {
663ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      if (offset_class_rule < class_set_end || offset_class_rule >= length) {
664ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        return OTS_FAILURE();
665ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      }
666ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      if (!ParseClassSetTable(data + offset_class_rule,
667ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              length - offset_class_rule, num_glyphs,
668ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              num_lookups)) {
669ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        return OTS_FAILURE();
670ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      }
671ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
672ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
673ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
674ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
675ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
676ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
677ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseContextFormat3(const uint8_t *data, const size_t length,
678ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_glyphs,
679ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                         const uint16_t num_lookups) {
680ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
681ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
682ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t glyph_count = 0;
683ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
684ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
685ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
686ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&glyph_count) ||
687ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&lookup_count)) {
688ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
689ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
690ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
691ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (glyph_count >= num_glyphs) {
692ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
693ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
69426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lookup_record_end = 2 * static_cast<unsigned>(glyph_count) +
69526afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      4 * static_cast<unsigned>(lookup_count) + 6;
696ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
697ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
698ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
699ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < glyph_count; ++i) {
700ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_coverage = 0;
701ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_coverage)) {
702ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
703ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
704ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_coverage < lookup_record_end || offset_coverage >= length) {
705ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
706ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
707ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseCoverageTable(data + offset_coverage,
708ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offset_coverage, num_glyphs)) {
709ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
710ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
711ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
712ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
713ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
714ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
715ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
716ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
717ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
718ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
719ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
720ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
721ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
722ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org// Parsers for Chaning Contextual subtables in GSUB/GPOS tables.
723ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
724ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainRuleSubtable(const uint8_t *data, const size_t length,
725ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_glyphs,
726ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_lookups) {
727ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
728ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
729ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t backtrack_count = 0;
730ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&backtrack_count)) {
731ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
732ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
733ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (backtrack_count >= num_glyphs) {
734ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
735ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
736ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < backtrack_count; ++i) {
737ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t glyph_id = 0;
738ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&glyph_id)) {
739ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
740ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
741ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (glyph_id > num_glyphs) {
742ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
743ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
744ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
745ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
746ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t input_count = 0;
747ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&input_count)) {
748ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
749ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
750ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (input_count == 0 || input_count >= num_glyphs) {
751ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
752ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
753ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < input_count - static_cast<unsigned>(1); ++i) {
754ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t glyph_id = 0;
755ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&glyph_id)) {
756ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
757ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
758ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (glyph_id > num_glyphs) {
759ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
760ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
761ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
762ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
763ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookahead_count = 0;
764ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookahead_count)) {
765ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
766ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
767ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookahead_count >= num_glyphs) {
768ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
769ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
770ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookahead_count; ++i) {
771ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t glyph_id = 0;
772ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&glyph_id)) {
773ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
774ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
775ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (glyph_id > num_glyphs) {
776ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
777ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
778ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
779ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
780ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
781ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookup_count)) {
782ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
783ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
784ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
785ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
786ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
787ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
788ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
789ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
790ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
791ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
792ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
793ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainRuleSetTable(const uint8_t *data, const size_t length,
794ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_glyphs,
795ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint16_t num_lookups) {
796ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
797ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
798ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t chain_rule_count = 0;
799ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&chain_rule_count)) {
800ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
801ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
80226afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned chain_rule_end =
80326afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(chain_rule_count) + 2;
804ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (chain_rule_end > std::numeric_limits<uint16_t>::max()) {
805ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
806ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
807ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < chain_rule_count; ++i) {
808ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_chain_rule = 0;
809ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_chain_rule)) {
810ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
811ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
812ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_chain_rule < chain_rule_end || offset_chain_rule >= length) {
813ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
814ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
815ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainRuleSubtable(data + offset_chain_rule,
816ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                length - offset_chain_rule,
817ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                num_glyphs, num_lookups)) {
818ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
819ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
820ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
821ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
822ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
823ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
824ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
825ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainContextFormat1(const uint8_t *data, const size_t length,
826ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_glyphs,
827ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_lookups) {
828ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
829ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
830ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_coverage = 0;
831ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t chain_rule_set_count = 0;
832ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
833ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
834ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_coverage) ||
835ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&chain_rule_set_count)) {
836ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
837ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
838ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
83926afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned chain_rule_set_end =
84026afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(chain_rule_set_count) + 6;
841ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (chain_rule_set_end > std::numeric_limits<uint16_t>::max()) {
842ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
843ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
844ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_coverage < chain_rule_set_end || offset_coverage >= length) {
845ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
846ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
847ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseCoverageTable(data + offset_coverage,
848ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_coverage, num_glyphs)) {
849ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
850ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
851ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
852ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < chain_rule_set_count; ++i) {
853ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_chain_rule_set = 0;
854ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_chain_rule_set)) {
855ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
856ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
857ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_chain_rule_set < chain_rule_set_end ||
858ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offset_chain_rule_set >= length) {
859ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
860ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
861ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainRuleSetTable(data + offset_chain_rule_set,
862ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                   length - offset_chain_rule_set,
863ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                   num_glyphs, num_lookups)) {
864ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
865ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
866ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
867ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
868ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
869ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
870ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
871ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainClassRuleSubtable(const uint8_t *data, const size_t length,
872ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 const uint16_t num_glyphs,
873ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 const uint16_t num_lookups) {
874ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
875ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
876ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // In this subtable, we don't check the value of classes for now since
877ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // these could take arbitrary values.
878ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
879ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t backtrack_count = 0;
880ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&backtrack_count)) {
881ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
882ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
883ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (backtrack_count >= num_glyphs) {
884ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
885ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
886ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2 * backtrack_count)) {
887ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
888ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
889ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
890ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t input_count = 0;
891ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&input_count)) {
892ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
893ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
894ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (input_count == 0 || input_count >= num_glyphs) {
895ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
896ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
897ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2 * (input_count - 1))) {
898ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
899ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
900ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
901ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookahead_count = 0;
902ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookahead_count)) {
903ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
904ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
905ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookahead_count >= num_glyphs) {
906ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
907ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
908ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2 * lookahead_count)) {
909ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
910ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
911ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
912ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
913ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookup_count)) {
914ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
915ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
916ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
917ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
918ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
919ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
920ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
921ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
922ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
923ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
924ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
925ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainClassSetTable(const uint8_t *data, const size_t length,
926ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                             const uint16_t num_glyphs,
927ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                             const uint16_t num_lookups) {
928ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
929ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
930ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t chain_class_rule_count = 0;
931ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&chain_class_rule_count)) {
932ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
933ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
93426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned chain_class_rule_end =
93526afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(chain_class_rule_count) + 2;
936ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (chain_class_rule_end > std::numeric_limits<uint16_t>::max()) {
937ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
938ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
939ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < chain_class_rule_count; ++i) {
940ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_chain_class_rule = 0;
941ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_chain_class_rule)) {
942ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
943ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
944ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_chain_class_rule < chain_class_rule_end ||
945ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offset_chain_class_rule >= length) {
946ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
947ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
948ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainClassRuleSubtable(data + offset_chain_class_rule,
949ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                     length - offset_chain_class_rule,
950ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                     num_glyphs, num_lookups)) {
951ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
952ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
953ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
954ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
955ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
956ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
957ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
958ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainContextFormat2(const uint8_t *data, const size_t length,
959ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_glyphs,
960ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_lookups) {
961ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
962ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
963ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_coverage = 0;
964ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_backtrack_class_def = 0;
965ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_input_class_def = 0;
966ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t offset_lookahead_class_def = 0;
967ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t chain_class_set_count = 0;
968ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
969ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
970ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_coverage) ||
971ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_backtrack_class_def) ||
972ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_input_class_def) ||
973ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&offset_lookahead_class_def) ||
974ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&chain_class_set_count)) {
975ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
976ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
977ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
97826afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned chain_class_set_end =
97926afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(chain_class_set_count) + 12;
980ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (chain_class_set_end > std::numeric_limits<uint16_t>::max()) {
981ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
982ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
983ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_coverage < chain_class_set_end || offset_coverage >= length) {
984ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
985ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
986ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseCoverageTable(data + offset_coverage,
987ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_coverage, num_glyphs)) {
988ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
989ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
990ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
991ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Classes for backtrack/lookahead sequences might not be defined.
992ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_backtrack_class_def) {
993ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_backtrack_class_def < chain_class_set_end ||
994ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offset_backtrack_class_def >= length) {
995ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
996ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
997ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseClassDefTable(data + offset_backtrack_class_def,
998ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offset_backtrack_class_def,
999ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 num_glyphs, kMaxClassDefValue)) {
1000ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1001ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1002ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1003ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1004ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_input_class_def < chain_class_set_end ||
1005ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      offset_input_class_def >= length) {
1006ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1007ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1008ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!ots::ParseClassDefTable(data + offset_input_class_def,
1009ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               length - offset_input_class_def,
1010ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                               num_glyphs, kMaxClassDefValue)) {
1011ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1012ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1013ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1014ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_lookahead_class_def) {
1015ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_lookahead_class_def < chain_class_set_end ||
1016ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offset_lookahead_class_def >= length) {
1017ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1018ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1019ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseClassDefTable(data + offset_lookahead_class_def,
1020ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offset_lookahead_class_def,
1021ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 num_glyphs, kMaxClassDefValue)) {
1022ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1023ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1024ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1025ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1026ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < chain_class_set_count; ++i) {
1027ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    uint16_t offset_chain_class_set = 0;
1028ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!subtable.ReadU16(&offset_chain_class_set)) {
1029ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1030ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1031ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    // |offset_chain_class_set| could be NULL.
1032ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offset_chain_class_set) {
1033ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      if (offset_chain_class_set < chain_class_set_end ||
1034ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org          offset_chain_class_set >= length) {
1035ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        return OTS_FAILURE();
1036ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      }
1037ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      if (!ParseChainClassSetTable(data + offset_chain_class_set,
1038ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                   length - offset_chain_class_set,
1039ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                   num_glyphs, num_lookups)) {
1040ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        return OTS_FAILURE();
1041ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      }
1042ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1043ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1044ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1045ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
1046ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1047ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1048ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainContextFormat3(const uint8_t *data, const size_t length,
1049ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_glyphs,
1050ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                              const uint16_t num_lookups) {
1051ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  ots::Buffer subtable(data, length);
1052ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1053ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t backtrack_count = 0;
1054ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Skip format field.
1055ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.Skip(2) ||
1056ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&backtrack_count)) {
1057ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1058ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1059ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1060ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (backtrack_count >= num_glyphs) {
1061ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1062ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1063ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  std::vector<uint16_t> offsets_backtrack;
1064ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  offsets_backtrack.reserve(backtrack_count);
1065ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < backtrack_count; ++i) {
1066e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    uint16_t offset = 0;
1067e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU16(&offset)) {
1068ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1069ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1070e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    offsets_backtrack.push_back(offset);
1071ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
10726b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (offsets_backtrack.size() != backtrack_count) {
10736b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
10746b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
1075ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1076ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t input_count = 0;
1077ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&input_count)) {
1078ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1079ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1080ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (input_count >= num_glyphs) {
1081ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1082ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1083ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  std::vector<uint16_t> offsets_input;
1084ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  offsets_input.reserve(input_count);
1085ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < input_count; ++i) {
1086e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    uint16_t offset = 0;
1087e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU16(&offset)) {
1088ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1089ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1090e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    offsets_input.push_back(offset);
1091ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
10926b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (offsets_input.size() != input_count) {
10936b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
10946b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
1095ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1096ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookahead_count = 0;
1097ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookahead_count)) {
1098ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1099ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1100ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookahead_count >= num_glyphs) {
1101ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1102ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1103ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  std::vector<uint16_t> offsets_lookahead;
1104ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  offsets_lookahead.reserve(lookahead_count);
1105ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookahead_count; ++i) {
1106e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    uint16_t offset = 0;
1107e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU16(&offset)) {
1108ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1109ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1110e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    offsets_lookahead.push_back(offset);
1111ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
11126b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (offsets_lookahead.size() != lookahead_count) {
11136b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
11146b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
1115ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1116ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_count = 0;
1117ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&lookup_count)) {
1118ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1119ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1120ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookup_count; ++i) {
1121ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseLookupRecord(&subtable, num_glyphs, num_lookups)) {
1122ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1123ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1124ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1125ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
112626afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lookup_record_end =
112726afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * (static_cast<unsigned>(backtrack_count) +
112826afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org           static_cast<unsigned>(input_count) +
112926afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org           static_cast<unsigned>(lookahead_count)) +
113026afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      4 * static_cast<unsigned>(lookup_count) + 10;
1131ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookup_record_end > std::numeric_limits<uint16_t>::max()) {
1132ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1133ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1134ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < backtrack_count; ++i) {
1135ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offsets_backtrack[i] < lookup_record_end ||
1136ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offsets_backtrack[i] >= length) {
1137ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1138ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1139ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseCoverageTable(data + offsets_backtrack[i],
1140ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offsets_backtrack[i], num_glyphs)) {
1141ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1142ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1143ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1144ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < input_count; ++i) {
1145ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offsets_input[i] < lookup_record_end || offsets_input[i] >= length) {
1146ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1147ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1148ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseCoverageTable(data + offsets_input[i],
1149ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offsets_input[i], num_glyphs)) {
1150ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1151ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1152ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1153ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < lookahead_count; ++i) {
1154ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (offsets_lookahead[i] < lookup_record_end ||
1155ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        offsets_lookahead[i] >= length) {
1156ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1157ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1158ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ots::ParseCoverageTable(data + offsets_lookahead[i],
1159ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 length - offsets_lookahead[i], num_glyphs)) {
1160ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1161ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1162ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1163ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1164ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
1165ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1166ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
116700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}  // namespace
116800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
116900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comnamespace ots {
117000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1171ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool LookupSubtableParser::Parse(const OpenTypeFile *file, const uint8_t *data,
1172ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 const size_t length,
1173ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                 const uint16_t lookup_type) const {
1174ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  for (unsigned i = 0; i < num_types; ++i) {
1175ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (parsers[i].type == lookup_type && parsers[i].parse) {
1176ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      if (!parsers[i].parse(file, data, length)) {
1177ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org        return OTS_FAILURE();
1178ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      }
1179ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return true;
1180ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1181ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1182ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return OTS_FAILURE();
1183ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1184ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
118578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// Parsing ScriptListTable requires number of features so we need to
118678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// parse FeatureListTable before calling this function.
118778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseScriptListTable(const uint8_t *data, const size_t length,
118878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                          const uint16_t num_features) {
118978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  Buffer subtable(data, length);
119078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
119178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t script_count = 0;
119278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&script_count)) {
119378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
119478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
119578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
119626afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned script_record_end =
119726afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      6 * static_cast<unsigned>(script_count) + 2;
119878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (script_record_end > std::numeric_limits<uint16_t>::max()) {
119978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
120078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
120178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  std::vector<ScriptRecord> script_list;
120278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  script_list.reserve(script_count);
120378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t last_tag = 0;
120478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < script_count; ++i) {
1205e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    ScriptRecord record;
1206e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU32(&record.tag) ||
1207e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org        !subtable.ReadU16(&record.offset)) {
120878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
120978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
121078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    // Script tags should be arranged alphabetically by tag
1211e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (last_tag != 0 && last_tag > record.tag) {
1212a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // Several fonts don't arrange tags alphabetically.
1213a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // It seems that the order of tags might not be a security issue
1214a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // so we just warn it.
1215a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      OTS_WARNING("tags aren't arranged alphabetically.");
121678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
1217e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    last_tag = record.tag;
1218e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (record.offset < script_record_end || record.offset >= length) {
121978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
122078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
1221e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    script_list.push_back(record);
122278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
12236b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (script_list.size() != script_count) {
12246b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
12256b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
122678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
122778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // Check script records.
122878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < script_count; ++i) {
122978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!ParseScriptTable(data + script_list[i].offset,
123078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                          length - script_list[i].offset,
123178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                          script_list[i].tag, num_features)) {
123278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
123378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
123478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
123578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
123678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
123778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
123878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
123978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// Parsing FeatureListTable requires number of lookups so we need to parse
124078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// LookupListTable before calling this function.
124178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseFeatureListTable(const uint8_t *data, const size_t length,
124278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                           const uint16_t num_lookups,
124378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                           uint16_t* num_features) {
124478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  Buffer subtable(data, length);
124578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
124678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t feature_count = 0;
124778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&feature_count)) {
124878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
124978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
125078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
125178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  std::vector<FeatureRecord> feature_records;
125278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  feature_records.resize(feature_count);
125326afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned feature_record_end =
125426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      6 * static_cast<unsigned>(feature_count) + 2;
125578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (feature_record_end > std::numeric_limits<uint16_t>::max()) {
125678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
125778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
125878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint32_t last_tag = 0;
125978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < feature_count; ++i) {
126078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!subtable.ReadU32(&feature_records[i].tag) ||
126178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com        !subtable.ReadU16(&feature_records[i].offset)) {
126278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
126378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
126478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    // Feature record array should be arranged alphabetically by tag
126578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (last_tag != 0 && last_tag > feature_records[i].tag) {
1266a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // Several fonts don't arrange tags alphabetically.
1267a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // It seems that the order of tags might not be a security issue
1268a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      // so we just warn it.
1269a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org      OTS_WARNING("tags aren't arranged alphabetically.");
127078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
127178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    last_tag = feature_records[i].tag;
127278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (feature_records[i].offset < feature_record_end ||
127378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com        feature_records[i].offset >= length) {
127478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
127578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
127678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
127778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
127878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < feature_count; ++i) {
127978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!ParseFeatureTable(data + feature_records[i].offset,
128078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                           length - feature_records[i].offset, num_lookups)) {
128178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
128278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
128378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
128478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  *num_features = feature_count;
128578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
128678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
128778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
128878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// For parsing GPOS/GSUB tables, this function should be called at first to
128978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// obtain the number of lookups because parsing FeatureTableList requires
129078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com// the number.
129178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseLookupListTable(OpenTypeFile *file, const uint8_t *data,
1292ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                          const size_t length,
1293ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                          const LookupSubtableParser* parser,
129478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com                          uint16_t *num_lookups) {
129578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  Buffer subtable(data, length);
129678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
129778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(num_lookups)) {
129878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
129978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
130078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
130178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  std::vector<uint16_t> lookups;
130278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  lookups.reserve(*num_lookups);
130326afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org  const unsigned lookup_end =
130426afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org      2 * static_cast<unsigned>(*num_lookups) + 2;
130578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (lookup_end > std::numeric_limits<uint16_t>::max()) {
130678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
130778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
130878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < *num_lookups; ++i) {
1309e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    uint16_t offset = 0;
1310e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (!subtable.ReadU16(&offset)) {
131178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
131278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
1313e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    if (offset < lookup_end || offset >= length) {
131478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
131578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
1316e2b566a774d999486a3d0388a9995aca63dcf46bbashi@chromium.org    lookups.push_back(offset);
131778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
13186b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  if (lookups.size() != *num_lookups) {
13196b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org    return OTS_FAILURE();
13206b41020e0a52fbc3a257a1b7652a0fcc92f6f9afbashi@chromium.org  }
132178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
132278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  for (unsigned i = 0; i < *num_lookups; ++i) {
132378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    if (!ParseLookupTable(file, data + lookups[i], length - lookups[i],
1324ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                          parser)) {
132578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      return OTS_FAILURE();
132678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    }
132778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
132878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
132978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
133078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
133178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
133200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseClassDefTable(const uint8_t *data, size_t length,
133300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                        const uint16_t num_glyphs,
133400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                        const uint16_t num_classes) {
133500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  Buffer subtable(data, length);
133600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
133700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t format = 0;
133800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&format)) {
133900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
134000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
134100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (format == 1) {
134200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return ParseClassDefFormat1(data, length, num_glyphs, num_classes);
134300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  } else if (format == 2) {
134400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return ParseClassDefFormat2(data, length, num_glyphs, num_classes);
134500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
134600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
134700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return OTS_FAILURE();
134800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
134900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
135000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.combool ParseCoverageTable(const uint8_t *data, size_t length,
1351eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                        const uint16_t num_glyphs,
1352eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org                        const uint16_t expected_num_glyphs) {
135300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  Buffer subtable(data, length);
135400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
135500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  uint16_t format = 0;
135600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (!subtable.ReadU16(&format)) {
135700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    return OTS_FAILURE();
135800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
135900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (format == 1) {
1360eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org    return ParseCoverageFormat1(data, length, num_glyphs, expected_num_glyphs);
136100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  } else if (format == 2) {
1362eea48361b1ffcc1bded0ba25c8f747e634cd8e51ksakamoto@chromium.org    return ParseCoverageFormat2(data, length, num_glyphs, expected_num_glyphs);
136300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
136400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
136500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return OTS_FAILURE();
136600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
136700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
136878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.combool ParseDeviceTable(const uint8_t *data, size_t length) {
136978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  Buffer subtable(data, length);
137078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
137178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t start_size = 0;
137278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t end_size = 0;
137378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  uint16_t delta_format = 0;
137478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.ReadU16(&start_size) ||
137578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&end_size) ||
137678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      !subtable.ReadU16(&delta_format)) {
137778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
137878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
137978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (start_size > end_size) {
138078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    OTS_WARNING("bad size range: %u > %u", start_size, end_size);
138178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
138278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
138378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (delta_format == 0 || delta_format > kMaxDeltaFormatType) {
138478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    OTS_WARNING("bad delta format: %u", delta_format);
138578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
138678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
138778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // The number of delta values per uint16. The device table should contain
138878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // at least |num_units| * 2 bytes compressed data.
138978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  const unsigned num_units = (end_size - start_size) /
139078a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      (1 << (4 - delta_format)) + 1;
139178a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // Just skip |num_units| * 2 bytes since the compressed data could take
139278a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  // arbitrary values.
139378a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  if (!subtable.Skip(num_units * 2)) {
139478a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    return OTS_FAILURE();
139578a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  }
139678a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  return true;
139778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com}
139878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com
1399ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseContextSubtable(const uint8_t *data, const size_t length,
1400ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                          const uint16_t num_glyphs,
1401ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                          const uint16_t num_lookups) {
1402ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  Buffer subtable(data, length);
1403ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1404ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t format = 0;
1405ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&format)) {
1406ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1407ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1408ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1409ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (format == 1) {
1410ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseContextFormat1(data, length, num_glyphs, num_lookups)) {
1411ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1412ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1413ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else if (format == 2) {
1414ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseContextFormat2(data, length, num_glyphs, num_lookups)) {
1415ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1416ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1417ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else if (format == 3) {
1418ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseContextFormat3(data, length, num_glyphs, num_lookups)) {
1419ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1420ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1421ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else {
1422ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1423ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1424ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1425ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
1426ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1427ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1428ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseChainingContextSubtable(const uint8_t *data, const size_t length,
1429ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                  const uint16_t num_glyphs,
1430ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                                  const uint16_t num_lookups) {
1431ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  Buffer subtable(data, length);
1432ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1433ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t format = 0;
1434ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&format)) {
1435ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1436ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1437ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1438ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (format == 1) {
1439ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainContextFormat1(data, length, num_glyphs, num_lookups)) {
1440ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1441ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1442ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else if (format == 2) {
1443ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainContextFormat2(data, length, num_glyphs, num_lookups)) {
1444ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1445ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1446ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else if (format == 3) {
1447ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    if (!ParseChainContextFormat3(data, length, num_glyphs, num_lookups)) {
1448ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      return OTS_FAILURE();
1449ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    }
1450ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  } else {
1451ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1452ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1453ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1454ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
1455ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1456ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1457ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.orgbool ParseExtensionSubtable(const OpenTypeFile *file,
1458ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const uint8_t *data, const size_t length,
1459ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                            const LookupSubtableParser* parser) {
1460ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  Buffer subtable(data, length);
1461ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1462ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t format = 0;
1463ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint16_t lookup_type = 0;
1464ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  uint32_t offset_extension = 0;
1465ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!subtable.ReadU16(&format) ||
1466ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU16(&lookup_type) ||
1467ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      !subtable.ReadU32(&offset_extension)) {
1468ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1469ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1470ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1471ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (format != 1) {
1472ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1473ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1474ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // |lookup_type| should be other than |parser->extension_type|.
1475ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (lookup_type < 1 || lookup_type > parser->num_types ||
1476ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      lookup_type == parser->extension_type) {
1477ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1478ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1479ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1480ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  const unsigned format_end = static_cast<unsigned>(8);
1481ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (offset_extension < format_end ||
1482ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org      offset_extension >= length) {
1483ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1484ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1485ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1486ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  // Parse the extension subtable of |lookup_type|.
1487ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  if (!parser->Parse(file, data + offset_extension, length - offset_extension,
1488ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org                     lookup_type)) {
1489ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org    return OTS_FAILURE();
1490ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  }
1491ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
1492ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org  return true;
1493ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org}
1494ced7112cb41d09cd344bbe4b20459049d6039491bashi@chromium.org
149500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}  // namespace ots
149600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1497