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