• 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)338 bool 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 
ParseCoverageFormat2(const uint8_t * data,size_t length,const uint16_t num_glyphs)369 bool 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 
ParseLookupRecord(ots::Buffer * subtable,const uint16_t num_glyphs,const uint16_t num_lookups)419 bool 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 
ParseRuleSubtable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)436 bool 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 
ParseRuleSetTable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)469 bool 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 
ParseContextFormat1(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)500 bool 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 
ParseClassRuleTable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)544 bool 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 
ParseClassSetTable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)575 bool 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 
ParseContextFormat2(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)607 bool 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 
ParseContextFormat3(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)664 bool 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 
ParseChainRuleSubtable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)711 bool 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 
ParseChainRuleSetTable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)780 bool 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 
ParseChainContextFormat1(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)812 bool 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 
ParseChainClassRuleSubtable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)858 bool 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 
ParseChainClassSetTable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)912 bool 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 
ParseChainContextFormat2(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)945 bool 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 
ParseChainContextFormat3(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)1035 bool 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 
1156 namespace ots {
1157 
Parse(const OpenTypeFile * file,const uint8_t * data,const size_t length,const uint16_t lookup_type) const1158 bool 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.
ParseScriptListTable(const uint8_t * data,const size_t length,const uint16_t num_features)1174 bool 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.
ParseFeatureListTable(const uint8_t * data,const size_t length,const uint16_t num_lookups,uint16_t * num_features)1228 bool 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.
ParseLookupListTable(OpenTypeFile * file,const uint8_t * data,const size_t length,const LookupSubtableParser * parser,uint16_t * num_lookups)1278 bool 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 
ParseClassDefTable(const uint8_t * data,size_t length,const uint16_t num_glyphs,const uint16_t num_classes)1319 bool 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 
ParseCoverageTable(const uint8_t * data,size_t length,const uint16_t num_glyphs)1337 bool 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 
ParseDeviceTable(const uint8_t * data,size_t length)1354 bool 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 
ParseContextSubtable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)1385 bool 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 
ParseChainingContextSubtable(const uint8_t * data,const size_t length,const uint16_t num_glyphs,const uint16_t num_lookups)1414 bool 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 
ParseExtensionSubtable(const OpenTypeFile * file,const uint8_t * data,const size_t length,const LookupSubtableParser * parser)1443 bool 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