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