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