1 #include "otlgpos.h" 2 #include "otlcommn.h" 3 4 /* forward declaration */ 5 static OTL_ValidateFunc otl_gpos_validate_funcs[]; 6 7 8 /************************************************************************/ 9 /************************************************************************/ 10 /***** *****/ 11 /***** VALUE RECORDS *****/ 12 /***** *****/ 13 /************************************************************************/ 14 /************************************************************************/ 15 16 static OTL_UInt otl_value_length(OTL_UInt format)17 otl_value_length( OTL_UInt format ) 18 { 19 FT_UInt count; 20 21 count = (( format & 0xAA ) >> 1) + ( format & 0x55 ); 22 count = (( count & 0xCC ) >> 2) + ( count & 0x33 ); 23 count = (( count & 0xF0 ) >> 4) + ( count & 0x0F ); 24 25 return count; 26 } 27 28 29 static void otl_value_validate(OTL_Bytes table,OTL_Bytes pos_table,OTL_UInt format,OTL_Validator valid)30 otl_value_validate( OTL_Bytes table, 31 OTL_Bytes pos_table, 32 OTL_UInt format, 33 OTL_Validator valid ) 34 { 35 OTL_Bytes p = table; 36 OTL_UInt count, device; 37 38 if ( format >= 0x100U ) 39 OTL_INVALID_DATA; 40 41 for ( count = 4; count > 0; count-- ) 42 { 43 if ( format & 1 ) 44 { 45 OTL_CHECK( 2 ); 46 p += 2; 47 } 48 49 format >>= 1; 50 } 51 52 for ( count = 4; count > 0; count-- ) 53 { 54 if ( format & 1 ) 55 { 56 OTL_CHECK( 2 ); 57 device = OTL_NEXT_USHORT( p ); 58 if ( device ) 59 otl_device_table_validate( pos_table + device, valid ); 60 } 61 format >>= 1; 62 } 63 } 64 65 66 /************************************************************************/ 67 /************************************************************************/ 68 /***** *****/ 69 /***** ANCHORS *****/ 70 /***** *****/ 71 /************************************************************************/ 72 /************************************************************************/ 73 74 static void otl_anchor_validate(OTL_Bytes table,OTL_Validator valid)75 otl_anchor_validate( OTL_Bytes table, 76 OTL_Validator valid ) 77 { 78 OTL_Bytes p = table; 79 OTL_UInt format; 80 81 OTL_CHECK( 6 ); 82 format = OTL_NEXT_USHORT( p ); 83 p += 4; 84 85 switch ( format ) 86 { 87 case 1: 88 break; 89 90 case 2: 91 OTL_CHECK( 2 ); /* anchor point */ 92 break; 93 94 case 3: 95 { 96 OTL_UInt x_device, y_device; 97 98 OTL_CHECK( 4 ); 99 x_device = OTL_NEXT_USHORT( p ); 100 y_device = OTL_NEXT_USHORT( p ); 101 102 if ( x_device ) 103 otl_device_table_validate( table + x_device, valid ); 104 105 if ( y_device ) 106 otl_device_table_validate( table + y_device, valid ); 107 } 108 break; 109 110 default: 111 OTL_INVALID_DATA; 112 } 113 } 114 115 116 /************************************************************************/ 117 /************************************************************************/ 118 /***** *****/ 119 /***** MARK ARRAY *****/ 120 /***** *****/ 121 /************************************************************************/ 122 /************************************************************************/ 123 124 static void otl_mark_array_validate(OTL_Bytes table,OTL_Validator valid)125 otl_mark_array_validate( OTL_Bytes table, 126 OTL_Validator valid ) 127 { 128 OTL_Bytes p = table; 129 OTL_UInt count; 130 131 OTL_CHECK( 2 ); 132 133 count = OTL_NEXT_USHORT( p ); 134 OTL_CHECK( count * 4 ); 135 for ( ; count > 0; count-- ) 136 { 137 p += 2; /* ignore class index */ 138 otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); 139 } 140 } 141 142 143 /************************************************************************/ 144 /************************************************************************/ 145 /***** *****/ 146 /***** GPOS LOOKUP TYPE 1 *****/ 147 /***** *****/ 148 /************************************************************************/ 149 /************************************************************************/ 150 151 static void otl_gpos_lookup1_validate(OTL_Bytes table,OTL_Validator valid)152 otl_gpos_lookup1_validate( OTL_Bytes table, 153 OTL_Validator valid ) 154 { 155 OTL_Bytes p = table; 156 OTL_UInt format; 157 158 OTL_CHECK( 2 ); 159 format = OTL_NEXT_USHORT( p ); 160 switch ( format ) 161 { 162 case 1: 163 { 164 FT_UInt coverage, value_format; 165 166 OTL_CHECK( 4 ); 167 coverage = OTL_NEXT_USHORT( p ); 168 value_format = OTL_NEXT_USHORT( p ); 169 170 otl_coverage_validate( table + coverage, valid ); 171 otl_value_validate( p, table, value_format, valid ); 172 } 173 break; 174 175 case 2: 176 { 177 FT_UInt coverage, value_format, count, len; 178 179 OTL_CHECK( 6 ); 180 coverage = OTL_NEXT_USHORT( p ); 181 value_format = OTL_NEXT_USHORT( p ); 182 count = OTL_NEXT_USHORT( p ); 183 len = otl_value_length( value_format ); 184 185 otl_coverage_validate( table + coverage, valid ); 186 187 OTL_CHECK( count * len ); 188 for ( ; count > 0; count-- ) 189 { 190 otl_value_validate( p, table, value_format, valid ); 191 p += len; 192 } 193 } 194 break; 195 196 default: 197 OTL_INVALID_DATA; 198 } 199 } 200 201 202 /************************************************************************/ 203 /************************************************************************/ 204 /***** *****/ 205 /***** GPOS LOOKUP TYPE 2 *****/ 206 /***** *****/ 207 /************************************************************************/ 208 /************************************************************************/ 209 otl_gpos_pairset_validate(OTL_Bytes table,OTL_Bytes pos_table,OTL_UInt format1,OTL_UInt format2,OTL_Validator valid)210 static otl_gpos_pairset_validate( OTL_Bytes table, 211 OTL_Bytes pos_table, 212 OTL_UInt format1, 213 OTL_UInt format2, 214 OTL_Validator valid ) 215 { 216 OTL_Bytes p = table; 217 OTL_UInt len1, len2, count; 218 219 OTL_CHECK( 2 ); 220 count = OTL_NEXT_USHORT( p ); 221 len1 = otl_value_length( format1 ); 222 len2 = otl_value_length( format2 ); 223 224 OTL_CHECK( count * (len1+len2+2) ); 225 for ( ; count > 0; count-- ) 226 { 227 p += 2; /* ignore glyph id */ 228 otl_value_validate( p, pos_table, format1, valid ); 229 p += len1; 230 231 otl_value_validate( p, pos_table, format2, valid ); 232 p += len2; 233 } 234 } 235 236 static void otl_gpos_lookup2_validate(OTL_Bytes table,OTL_Validator valid)237 otl_gpos_lookup2_validate( OTL_Bytes table, 238 OTL_Validator valid ) 239 { 240 OTL_Bytes p = table; 241 OTL_UInt format; 242 243 OTL_CHECK( 2 ); 244 format = OTL_NEXT_USHORT( p ); 245 switch (format) 246 { 247 case 1: 248 { 249 OTL_UInt coverage, value1, value2, count; 250 251 OTL_CHECK( 8 ); 252 coverage = OTL_NEXT_USHORT( p ); 253 value1 = OTL_NEXT_USHORT( p ); 254 value2 = OTL_NEXT_USHORT( p ); 255 count = OTL_NEXT_USHORT( p ); 256 257 otl_coverage_validate( table + coverage, valid ); 258 259 OTL_CHECK( count*2 ); 260 for ( ; count > 0; count-- ) 261 { 262 otl_gpos_pairset_validate( table + OTL_NEXT_USHORT( p ), 263 table, value1, value2, valid ); 264 } 265 } 266 break; 267 268 case 2: 269 { 270 OTL_UInt coverage, value1, value2, class1, class2, count1, count2; 271 OTL_UInt len1, len2; 272 273 OTL_CHECK( 14 ); 274 coverage = OTL_NEXT_USHORT( p ); 275 value1 = OTL_NEXT_USHORT( p ); 276 value2 = OTL_NEXT_USHORT( p ); 277 class1 = OTL_NEXT_USHORT( p ); 278 class2 = OTL_NEXT_USHORT( p ); 279 count1 = OTL_NEXT_USHORT( p ); 280 count2 = OTL_NEXT_USHORT( p ); 281 282 len1 = otl_value_length( value1 ); 283 len2 = otl_value_length( value2 ); 284 285 otl_coverage_validate( table + coverage, valid ); 286 287 OTL_CHECK( count1*count2*(len1+len2) ); 288 for ( ; count1 > 0; count1-- ) 289 { 290 for ( ; count2 > 0; count2-- ) 291 { 292 otl_value_validate( p, table, value1, valid ); 293 p += len1; 294 295 otl_value_validate( p, table, value2, valid ); 296 p += len2; 297 } 298 } 299 } 300 break; 301 302 default: 303 OTL_INVALID_DATA; 304 } 305 } 306 307 308 /************************************************************************/ 309 /************************************************************************/ 310 /***** *****/ 311 /***** GPOS LOOKUP TYPE 3 *****/ 312 /***** *****/ 313 /************************************************************************/ 314 /************************************************************************/ 315 316 static void otl_gpos_lookup3_validate(OTL_Bytes table,OTL_Valid valid)317 otl_gpos_lookup3_validate( OTL_Bytes table, 318 OTL_Valid valid ) 319 { 320 OTL_Bytes p = table; 321 OTL_UInt format; 322 323 OTL_CHECK( 2 ); 324 format = OTL_NEXT_USHORT( p ); 325 switch (format) 326 { 327 case 1: 328 { 329 OTL_UInt coverage, count, anchor1, anchor2; 330 331 OTL_CHECK( 4 ); 332 coverage = OTL_NEXT_USHORT( p ); 333 count = OTL_NEXT_USHORT( p ); 334 335 otl_coverage_validate( table + coverage, valid ); 336 337 OTL_CHECK( count*4 ); 338 for ( ; count > 0; count-- ) 339 { 340 anchor1 = OTL_NEXT_USHORT( p ); 341 anchor2 = OTL_NEXT_USHORT( p ); 342 343 if ( anchor1 ) 344 otl_anchor_validate( table + anchor1, valid ); 345 346 if ( anchor2 ) 347 otl_anchor_validate( table + anchor2, valid ); 348 } 349 } 350 break; 351 352 default: 353 OTL_INVALID_DATA; 354 } 355 } 356 357 358 /************************************************************************/ 359 /************************************************************************/ 360 /***** *****/ 361 /***** GPOS LOOKUP TYPE 4 *****/ 362 /***** *****/ 363 /************************************************************************/ 364 /************************************************************************/ 365 366 static void otl_base_array_validate(OTL_Bytes table,OTL_UInt class_count,OTL_Validator valid)367 otl_base_array_validate( OTL_Bytes table, 368 OTL_UInt class_count, 369 OTL_Validator valid ) 370 { 371 OTL_Bytes p = table; 372 OTL_UInt count, count2; 373 374 OTL_CHECK( 2 ); 375 count = OTL_NEXT_USHORT( p ); 376 377 OTL_CHECK( count*class_count*2 ); 378 for ( ; count > 0; count-- ) 379 for ( count2 = class_count; count2 > 0; count2-- ) 380 otl_anchor_validate( table + OTL_NEXT_USHORT( p ) ); 381 } 382 383 384 static void otl_gpos_lookup4_validate(OTL_Bytes table,OTL_Valid valid)385 otl_gpos_lookup4_validate( OTL_Bytes table, 386 OTL_Valid valid ) 387 { 388 OTL_Bytes p = table; 389 OTL_UInt format; 390 391 OTL_CHECK( 2 ); 392 format = OTL_NEXT_USHORT( p ); 393 switch (format) 394 { 395 case 1: 396 { 397 OTL_UInt mark_coverage, base_coverage, class_count; 398 OTL_UInt mark_array, base_array; 399 400 OTL_CHECK( 10 ); 401 mark_coverage = OTL_NEXT_USHORT( p ); 402 base_coverage = OTL_NEXT_USHORT( p ); 403 class_count = OTL_NEXT_USHORT( p ); 404 mark_array = OTL_NEXT_USHORT( p ); 405 base_array = OTL_NEXT_USHORT( p ); 406 407 otl_coverage_validate( table + mark_coverage, valid ); 408 otl_coverage_validate( table + base_coverage, valid ); 409 410 otl_mark_array_validate( table + mark_array, valid ); 411 otl_base_array_validate( table, class_count, valid ); 412 } 413 break; 414 415 default: 416 OTL_INVALID_DATA; 417 } 418 } 419 420 /************************************************************************/ 421 /************************************************************************/ 422 /***** *****/ 423 /***** GPOS LOOKUP TYPE 5 *****/ 424 /***** *****/ 425 /************************************************************************/ 426 /************************************************************************/ 427 428 static void otl_liga_attach_validate(OTL_Bytes table,OTL_UInt class_count,OTL_Validator valid)429 otl_liga_attach_validate( OTL_Bytes table, 430 OTL_UInt class_count, 431 OTL_Validator valid ) 432 { 433 OTL_Bytes p = table; 434 OTL_UInt count, count2; 435 436 OTL_CHECK( 2 ); 437 count = OTL_NEXT_USHORT( p ); 438 439 OTL_CHECK( count*class_count*2 ); 440 for ( ; count > 0; count-- ) 441 for ( count2 = class_count; class_count > 0; class_count-- ) 442 otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); 443 } 444 445 446 static void otl_liga_array_validate(OTL_Bytes table,OTL_UInt class_count,OTL_Validator valid)447 otl_liga_array_validate( OTL_Bytes table, 448 OTL_UInt class_count, 449 OTL_Validator valid ) 450 { 451 OTL_Bytes p = table; 452 OTL_UInt count, count2; 453 454 OTL_CHECK( 2 ); 455 count = OTL_NEXT_USHORT( p ); 456 457 OTL_CHECK( count*2 ); 458 for ( ; count > 0; count-- ) 459 otl_liga_attach_validate( table + OTL_NEXT_USHORT( p ), valid ); 460 } 461 462 463 static void otl_gpos_lookup5_validate(OTL_Bytes table,OTL_Valid valid)464 otl_gpos_lookup5_validate( OTL_Bytes table, 465 OTL_Valid valid ) 466 { 467 OTL_Bytes p = table; 468 OTL_UInt format; 469 470 OTL_CHECK( 2 ); 471 format = OTL_NEXT_USHORT( p ); 472 switch (format) 473 { 474 case 1: 475 { 476 OTL_UInt mark_coverage, lig_coverage, class_count; 477 OTL_UInt mar_array, lig_array; 478 479 OTL_CHECK( 10 ); 480 mark_coverage = OTL_NEXT_USHORT( p ); 481 liga_coverage = OTL_NEXT_USHORT( p ); 482 class_count = OTL_NEXT_USHORT( p ); 483 mark_array = OTL_NEXT_USHORT( p ); 484 liga_array = OTL_NEXT_USHORT( p ); 485 486 otl_coverage_validate( table + mark_coverage, valid ); 487 otl_coverage_validate( table + liga_coverage, valid ); 488 489 otl_mark_array_validate( table + mark_array, valid ); 490 otl_liga_array_validate( table + liga_array, class_count, valid ); 491 } 492 break; 493 494 default: 495 OTL_INVALID_DATA; 496 } 497 } 498 499 /************************************************************************/ 500 /************************************************************************/ 501 /***** *****/ 502 /***** GPOS LOOKUP TYPE 6 *****/ 503 /***** *****/ 504 /************************************************************************/ 505 /************************************************************************/ 506 507 508 static void otl_mark2_array_validate(OTL_Bytes table,OTL_UInt class_count,OTL_Validator valid)509 otl_mark2_array_validate( OTL_Bytes table, 510 OTL_UInt class_count, 511 OTL_Validator valid ) 512 { 513 OTL_Bytes p = table; 514 OTL_UInt count, count2; 515 516 OTL_CHECK( 2 ); 517 count = OTL_NEXT_USHORT( p ); 518 519 OTL_CHECK( count*class_count*2 ); 520 for ( ; count > 0; count-- ) 521 for ( count2 = class_count; class_count > 0; class_count-- ) 522 otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid ); 523 } 524 525 526 static void otl_gpos_lookup6_validate(OTL_Bytes table,OTL_Valid valid)527 otl_gpos_lookup6_validate( OTL_Bytes table, 528 OTL_Valid valid ) 529 { 530 OTL_Bytes p = table; 531 OTL_UInt format; 532 533 OTL_CHECK( 2 ); 534 format = OTL_NEXT_USHORT( p ); 535 switch (format) 536 { 537 case 1: 538 { 539 OTL_UInt coverage1, coverage2, class_count, array1, array2; 540 541 OTL_CHECK( 10 ); 542 coverage1 = OTL_NEXT_USHORT( p ); 543 coverage2 = OTL_NEXT_USHORT( p ); 544 class_count = OTL_NEXT_USHORT( p ); 545 array1 = OTL_NEXT_USHORT( p ); 546 array2 = OTL_NEXT_USHORT( p ); 547 548 otl_coverage_validate( table + coverage1, valid ); 549 otl_coverage_validate( table + coverage2, valid ); 550 551 otl_mark_array_validate( table + array1, valid ); 552 otl_mark2_array_validate( table + array2, valid ); 553 } 554 break; 555 556 default: 557 OTL_INVALID_DATA; 558 } 559 } 560 561 562 /************************************************************************/ 563 /************************************************************************/ 564 /***** *****/ 565 /***** GPOS LOOKUP TYPE 7 *****/ 566 /***** *****/ 567 /************************************************************************/ 568 /************************************************************************/ 569 570 static void otl_pos_rule_validate(OTL_Bytes table,OTL_Validator valid)571 otl_pos_rule_validate( OTL_Bytes table, 572 OTL_Validator valid ) 573 { 574 OTL_Bytes p = table; 575 OTL_UInt glyph_count, pos_count; 576 577 OTL_CHECK( 4 ); 578 glyph_count = OTL_NEXT_USHORT( p ); 579 pos_count = OTL_NEXT_USHORT( p ); 580 581 if ( glyph_count == 0 ) 582 OTL_INVALID_DATA; 583 584 OTL_CHECK( (glyph_count-1)*2 + pos_count*4 ); 585 586 /* XXX: check glyph indices and pos lookups */ 587 } 588 589 590 static void otl_pos_rule_set_validate(OTL_Bytes table,OTL_Validator valid)591 otl_pos_rule_set_validate( OTL_Bytes table, 592 OTL_Validator valid ) 593 { 594 OTL_Bytes p = table; 595 OTL_UInt count; 596 597 OTL_CHECK( 2 ); 598 count = OTL_NEXT_USHORT( p ); 599 600 OTL_CHECK( count*2 ); 601 for ( ; count > 0; count-- ) 602 otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid ); 603 } 604 605 606 607 static void otl_pos_class_rule_validate(OTL_Bytes table,OTL_Validator valid)608 otl_pos_class_rule_validate( OTL_Bytes table, 609 OTL_Validator valid ) 610 { 611 OTL_Bytes p = table; 612 OTL_UInt glyph_count, pos_count; 613 614 OTL_CHECK( 4 ); 615 glyph_count = OTL_NEXT_USHORT( p ); 616 pos_count = OTL_NEXT_USHORT( p ); 617 618 if ( glyph_count == 0 ) 619 OTL_INVALID_DATA; 620 621 OTL_CHECK( (glyph_count-1)*2 + pos_count*4 ); 622 623 /* XXX: check glyph indices and pos lookups */ 624 } 625 626 627 static void otl_pos_class_set_validate(OTL_Bytes table,OTL_Validator valid)628 otl_pos_class_set_validate( OTL_Bytes table, 629 OTL_Validator valid ) 630 { 631 OTL_Bytes p = table; 632 OTL_UInt count; 633 634 OTL_CHECK( 2 ); 635 count = OTL_NEXT_USHORT( p ); 636 637 OTL_CHECK( count*2 ); 638 for ( ; count > 0; count-- ) 639 otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid ); 640 } 641 642 643 static void otl_gpos_lookup7_validate(OTL_Bytes table,OTL_Validator valid)644 otl_gpos_lookup7_validate( OTL_Bytes table, 645 OTL_Validator valid ) 646 { 647 OTL_Bytes p = table; 648 OTL_UInt format; 649 650 OTL_CHECK( 2 ); 651 format = OTL_NEXT_USHORT( p ); 652 switch (format) 653 { 654 case 1: 655 { 656 OTL_UInt coverage, count; 657 658 OTL_CHECK( 4 ); 659 coverage = OTL_NEXT_USHORT( p ); 660 count = OTL_NEXT_USHORT( p ); 661 662 otl_coverage_validate( table + coverage, valid ); 663 664 OTL_CHECK( count*2 ); 665 for ( ; count > 0; count-- ) 666 otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid ); 667 } 668 break; 669 670 case 2: 671 { 672 OTL_UInt coverage, class_def, count; 673 674 OTL_CHECK( 6 ); 675 coverage = OTL_NEXT_USHORT( p ); 676 class_def = OTL_NEXT_USHORT( p ); 677 count = OTL_NEXT_USHORT( p ); 678 679 otl_coverage_validate ( table + coverage, valid ); 680 otl_class_definition_validate( table + class_def, valid ); 681 682 OTL_CHECK( count*2 ); 683 for ( ; count > 0; count-- ) 684 otl_ 685 } 686 break; 687 688 case 3: 689 { 690 OTL_UInt glyph_count, pos_count; 691 692 OTL_CHECK( 4 ); 693 glyph_count = OTL_NEXT_USHORT( p ); 694 pos_count = OTL_NEXT_USHORT( p ); 695 696 OTL_CHECK( glyph_count*2 + pos_count*4 ); 697 for ( ; glyph_count > 0; glyph_count ) 698 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 699 700 /* XXX: check pos lookups */ 701 } 702 break; 703 704 default: 705 OTL_INVALID_DATA; 706 } 707 } 708 709 710 /************************************************************************/ 711 /************************************************************************/ 712 /***** *****/ 713 /***** GPOS LOOKUP TYPE 8 *****/ 714 /***** *****/ 715 /************************************************************************/ 716 /************************************************************************/ 717 718 static void otl_chain_pos_rule_validate(OTL_Bytes table,OTL_Validator valid)719 otl_chain_pos_rule_validate( OTL_Bytes table, 720 OTL_Validator valid ) 721 { 722 OTL_Bytes p = table; 723 OTL_UInt back_count, input_count, ahead_count, pos_count; 724 725 OTL_CHECK( 2 ); 726 back_count = OTL_NEXT_USHORT( p ); 727 728 OTL_CHECK( back_count*2 + 2 ); 729 p += back_count*2; 730 731 input_count = OTL_NEXT_USHORT( p ); 732 if ( input_count == 0 ) 733 OTL_INVALID_DATA; 734 735 OTL_CHECK( input_count*2 ); 736 p += (input_count-1)*2; 737 738 ahead_count = OTL_NEXT_USHORT( p ); 739 OTL_CHECK( ahead_count*2 + 2 ); 740 p += ahead_count*2; 741 742 pos_count = OTL_NEXT_USHORT( p ); 743 OTL_CHECK( pos_count*4 ); 744 } 745 746 747 static void otl_chain_pos_rule_set_validate(OTL_Bytes table,OTL_Validator valid)748 otl_chain_pos_rule_set_validate( OTL_Bytes table, 749 OTL_Validator valid ) 750 { 751 OTL_Bytes p = table; 752 OTL_UInt count; 753 754 OTL_CHECK( 2 ); 755 count = OTL_NEXT_USHORT( p ); 756 757 OTL_CHECK( 2*count ); 758 for ( ; count > 0; count-- ) 759 otl_chain_pos_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 760 } 761 762 763 764 static void otl_chain_pos_class_rule_validate(OTL_Bytes table,OTL_Validator valid)765 otl_chain_pos_class_rule_validate( OTL_Bytes table, 766 OTL_Validator valid ) 767 { 768 OTL_Bytes p = table; 769 OTL_UInt back_count, input_count, ahead_count, pos_count; 770 771 OTL_CHECK( 2 ); 772 back_count = OTL_NEXT_USHORT( p ); 773 774 OTL_CHECK( back_count*2 + 2 ); 775 p += back_count*2; 776 777 input_count = OTL_NEXT_USHORT( p ); 778 if ( input_count == 0 ) 779 OTL_INVALID_DATA; 780 781 OTL_CHECK( input_count*2 ); 782 p += (input_count-1)*2; 783 784 ahead_count = OTL_NEXT_USHORT( p ); 785 OTL_CHECK( ahead_count*2 + 2 ); 786 p += ahead_count*2; 787 788 pos_count = OTL_NEXT_USHORT( p ); 789 OTL_CHECK( pos_count*4 ); 790 } 791 792 793 static void otl_chain_pos_class_set_validate(OTL_Bytes table,OTL_Validator valid)794 otl_chain_pos_class_set_validate( OTL_Bytes table, 795 OTL_Validator valid ) 796 { 797 OTL_Bytes p = table; 798 OTL_UInt count; 799 800 OTL_CHECK( 2 ); 801 count = OTL_NEXT_USHORT( p ); 802 803 OTL_CHECK( 2*count ); 804 for ( ; count > 0; count-- ) 805 otl_chain_pos_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 806 } 807 808 809 static void otl_gpos_lookup8_validate(OTL_Bytes table,OTL_Validator valid)810 otl_gpos_lookup8_validate( OTL_Bytes table, 811 OTL_Validator valid ) 812 { 813 OTL_Bytes p = table; 814 OTL_UInt format; 815 816 OTL_CHECK( 2 ); 817 format = OTL_NEXT_USHORT( p ); 818 switch (format) 819 { 820 case 1: 821 { 822 OTL_UInt coverage, count; 823 824 OTL_CHECK( 4 ); 825 coverage = OTL_NEXT_USHORT( p ); 826 count = OTL_NEXT_USHORT( p ); 827 828 otl_coverage_validate( table + coverage, valid ); 829 830 OTL_CHECK( count*2 ); 831 for ( ; count > 0; count-- ) 832 otl_chain_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), 833 valid ); 834 } 835 break; 836 837 case 2: 838 { 839 OTL_UInt coverage, back_class, input_class, ahead_class, count; 840 841 OTL_CHECK( 10 ); 842 coverage = OTL_NEXT_USHORT( p ); 843 back_class = OTL_NEXT_USHORT( p ); 844 input_class = OTL_NEXT_USHORT( p ); 845 ahead_class = OTL_NEXT_USHORT( p ); 846 count = OTL_NEXT_USHORT( p ); 847 848 otl_coverage_validate( table + coverage, valid ); 849 850 otl_class_definition_validate( table + back_class, valid ); 851 otl_class_definition_validate( table + input_class, valid ); 852 otl_class_definition_validate( table + ahead_class, valid ); 853 854 OTL_CHECK( count*2 ); 855 for ( ; count > 0; count-- ) 856 otl_chain_pos_class_set_validate( table + OTL_NEXT_USHORT( p ), 857 valid ); 858 } 859 break; 860 861 case 3: 862 { 863 OTL_UInt back_count, input_count, ahead_count, pos_count, count; 864 865 OTL_CHECK( 2 ); 866 back_count = OTL_NEXT_USHORT( p ); 867 868 OTL_CHECK( 2*back_count+2 ); 869 for ( count = back_count; count > 0; count-- ) 870 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 871 872 input_count = OTL_NEXT_USHORT( p ); 873 874 OTL_CHECK( 2*input_count+2 ); 875 for ( count = input_count; count > 0; count-- ) 876 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 877 878 ahead_count = OTL_NEXT_USHORT( p ); 879 880 OTL_CHECK( 2*ahead_count+2 ); 881 for ( count = ahead_count; count > 0; count-- ) 882 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 883 884 pos_count = OTL_NEXT_USHORT( p ); 885 OTL_CHECK( pos_count*4 ); 886 } 887 break; 888 889 default: 890 OTL_INVALID_DATA; 891 } 892 } 893 894 /************************************************************************/ 895 /************************************************************************/ 896 /***** *****/ 897 /***** GPOS LOOKUP TYPE 9 *****/ 898 /***** *****/ 899 /************************************************************************/ 900 /************************************************************************/ 901 902 static void otl_gpos_lookup9_validate(OTL_Bytes table,OTL_Valid valid)903 otl_gpos_lookup9_validate( OTL_Bytes table, 904 OTL_Valid valid ) 905 { 906 OTL_Bytes p = table; 907 OTL_UInt format; 908 909 OTL_CHECK( 2 ); 910 format = OTL_NEXT_USHORT( p ); 911 switch (format) 912 { 913 case 1: 914 { 915 OTL_UInt lookup_type, lookup_offset; 916 OTL_ValidateFunc validate; 917 918 OTL_CHECK( 6 ); 919 lookup_type = OTL_NEXT_USHORT( p ); 920 lookup_offset = OTL_NEXT_ULONG( p ); 921 922 if ( lookup_type == 0 || lookup_type >= 9 ) 923 OTL_INVALID_DATA; 924 925 validate = otl_gpos_validate_funcs[ lookup_type-1 ]; 926 validate( table + lookup_offset, valid ); 927 } 928 break; 929 930 default: 931 OTL_INVALID_DATA; 932 } 933 } 934 935 static OTL_ValidateFunc otl_gpos_validate_funcs[ 9 ] = 936 { 937 otl_gpos_lookup1_validate, 938 otl_gpos_lookup2_validate, 939 otl_gpos_lookup3_validate, 940 otl_gpos_lookup4_validate, 941 otl_gpos_lookup5_validate, 942 otl_gpos_lookup6_validate, 943 otl_gpos_lookup7_validate, 944 otl_gpos_lookup8_validate, 945 otl_gpos_lookup9_validate, 946 }; 947 948 949 /************************************************************************/ 950 /************************************************************************/ 951 /***** *****/ 952 /***** GPOS TABLE *****/ 953 /***** *****/ 954 /************************************************************************/ 955 /************************************************************************/ 956 957 958 OTL_LOCALDEF( void ) otl_gpos_validate(OTL_Bytes table,OTL_Validator valid)959 otl_gpos_validate( OTL_Bytes table, 960 OTL_Validator valid ) 961 { 962 OTL_Bytes p = table; 963 OTL_UInt scripts, features, lookups; 964 965 OTL_CHECK( 10 ); 966 967 if ( OTL_NEXT_USHORT( p ) != 0x10000UL ) 968 OTL_INVALID_DATA; 969 970 scripts = OTL_NEXT_USHORT( p ); 971 features = OTL_NEXT_USHORT( p ); 972 lookups = OTL_NEXT_USHORT( p ); 973 974 otl_script_list_validate ( table + scripts, valid ); 975 otl_feature_list_validate( table + features, valid ); 976 977 otl_lookup_list_validate( table + lookups, 9, otl_gpos_validate_funcs, 978 valid ); 979 } 980