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