1 // Copyright (c) 2010 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 // A parser for the Type 2 Charstring Format. 6 // http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf 7 8 #include "cff_type2_charstring.h" 9 10 #include <climits> 11 #include <cstdio> 12 #include <cstring> 13 #include <stack> 14 #include <string> 15 #include <utility> 16 17 namespace { 18 19 // Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical 20 // Note #5177. 21 const int32_t kMaxSubrsCount = 65536; 22 const size_t kMaxCharStringLength = 65535; 23 const size_t kMaxArgumentStack = 48; 24 const size_t kMaxNumberOfStemHints = 96; 25 const size_t kMaxSubrNesting = 10; 26 27 // |dummy_result| should be a huge positive integer so callsubr and callgsubr 28 // will fail with the dummy value. 29 const int32_t dummy_result = INT_MAX; 30 31 bool ExecuteType2CharString(size_t call_depth, 32 const ots::CFFIndex& global_subrs_index, 33 const ots::CFFIndex& local_subrs_index, 34 ots::Buffer *cff_table, 35 ots::Buffer *char_string, 36 std::stack<int32_t> *argument_stack, 37 bool *out_found_endchar, 38 bool *out_found_width, 39 size_t *in_out_num_stems); 40 41 // Read one or more bytes from the |char_string| buffer and stores the number 42 // read on |out_number|. If the number read is an operator (ex 'vstem'), sets 43 // true on |out_is_operator|. Returns true if the function read a number. 44 bool ReadNextNumberFromType2CharString(ots::Buffer *char_string, 45 int32_t *out_number, 46 bool *out_is_operator) { 47 uint8_t v = 0; 48 if (!char_string->ReadU8(&v)) { 49 return OTS_FAILURE(); 50 } 51 *out_is_operator = false; 52 53 // The conversion algorithm is described in Adobe Technical Note #5177, page 54 // 13, Table 1. 55 if (v <= 11) { 56 *out_number = v; 57 *out_is_operator = true; 58 } else if (v == 12) { 59 uint16_t result = (v << 8); 60 if (!char_string->ReadU8(&v)) { 61 return OTS_FAILURE(); 62 } 63 result += v; 64 *out_number = result; 65 *out_is_operator = true; 66 } else if (v <= 27) { 67 // Special handling for v==19 and v==20 are implemented in 68 // ExecuteType2CharStringOperator(). 69 *out_number = v; 70 *out_is_operator = true; 71 } else if (v == 28) { 72 if (!char_string->ReadU8(&v)) { 73 return OTS_FAILURE(); 74 } 75 uint16_t result = (v << 8); 76 if (!char_string->ReadU8(&v)) { 77 return OTS_FAILURE(); 78 } 79 result += v; 80 *out_number = result; 81 } else if (v <= 31) { 82 *out_number = v; 83 *out_is_operator = true; 84 } else if (v <= 246) { 85 *out_number = static_cast<int32_t>(v) - 139; 86 } else if (v <= 250) { 87 uint8_t w = 0; 88 if (!char_string->ReadU8(&w)) { 89 return OTS_FAILURE(); 90 } 91 *out_number = ((static_cast<int32_t>(v) - 247) * 256) + 92 static_cast<int32_t>(w) + 108; 93 } else if (v <= 254) { 94 uint8_t w = 0; 95 if (!char_string->ReadU8(&w)) { 96 return OTS_FAILURE(); 97 } 98 *out_number = -((static_cast<int32_t>(v) - 251) * 256) - 99 static_cast<int32_t>(w) - 108; 100 } else if (v == 255) { 101 // TODO(yusukes): We should not skip the 4 bytes. Note that when v is 255, 102 // we should treat the following 4-bytes as a 16.16 fixed-point number 103 // rather than 32bit signed int. 104 if (!char_string->Skip(4)) { 105 return OTS_FAILURE(); 106 } 107 *out_number = dummy_result; 108 } else { 109 return OTS_FAILURE(); 110 } 111 112 return true; 113 } 114 115 // Executes |op| and updates |argument_stack|. Returns true if the execution 116 // succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively 117 // calls ExecuteType2CharString() function. The arguments other than |op| and 118 // |argument_stack| are passed for that reason. 119 bool ExecuteType2CharStringOperator(int32_t op, 120 size_t call_depth, 121 const ots::CFFIndex& global_subrs_index, 122 const ots::CFFIndex& local_subrs_index, 123 ots::Buffer *cff_table, 124 ots::Buffer *char_string, 125 std::stack<int32_t> *argument_stack, 126 bool *out_found_endchar, 127 bool *in_out_found_width, 128 size_t *in_out_num_stems) { 129 const size_t stack_size = argument_stack->size(); 130 131 switch (op) { 132 case ots::kCallSubr: 133 case ots::kCallGSubr: { 134 const ots::CFFIndex& subrs_index = 135 (op == ots::kCallSubr ? local_subrs_index : global_subrs_index); 136 137 if (stack_size < 1) { 138 return OTS_FAILURE(); 139 } 140 int32_t subr_number = argument_stack->top(); 141 argument_stack->pop(); 142 if (subr_number == dummy_result) { 143 // For safety, we allow subr calls only with immediate subr numbers for 144 // now. For example, we allow "123 callgsubr", but does not allow "100 12 145 // add callgsubr". Please note that arithmetic and conditional operators 146 // always push the |dummy_result| in this implementation. 147 return OTS_FAILURE(); 148 } 149 150 // See Adobe Technical Note #5176 (CFF), "16. Local/GlobalSubrs INDEXes." 151 int32_t bias = 32768; 152 if (subrs_index.count < 1240) { 153 bias = 107; 154 } else if (subrs_index.count < 33900) { 155 bias = 1131; 156 } 157 subr_number += bias; 158 159 // Sanity checks of |subr_number|. 160 if (subr_number < 0) { 161 return OTS_FAILURE(); 162 } 163 if (subr_number >= kMaxSubrsCount) { 164 return OTS_FAILURE(); 165 } 166 if (subrs_index.offsets.size() <= static_cast<size_t>(subr_number + 1)) { 167 return OTS_FAILURE(); // The number is out-of-bounds. 168 } 169 170 // Prepare ots::Buffer where we're going to jump. 171 const size_t length = 172 subrs_index.offsets[subr_number + 1] - subrs_index.offsets[subr_number]; 173 if (length > kMaxCharStringLength) { 174 return OTS_FAILURE(); 175 } 176 const size_t offset = subrs_index.offsets[subr_number]; 177 cff_table->set_offset(offset); 178 if (!cff_table->Skip(length)) { 179 return OTS_FAILURE(); 180 } 181 ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length); 182 183 return ExecuteType2CharString(call_depth + 1, 184 global_subrs_index, 185 local_subrs_index, 186 cff_table, 187 &char_string_to_jump, 188 argument_stack, 189 out_found_endchar, 190 in_out_found_width, 191 in_out_num_stems); 192 } 193 194 case ots::kReturn: 195 return true; 196 197 case ots::kEndChar: 198 *out_found_endchar = true; 199 *in_out_found_width = true; // just in case. 200 return true; 201 202 case ots::kHStem: 203 case ots::kVStem: 204 case ots::kHStemHm: 205 case ots::kVStemHm: { 206 bool successful = false; 207 if (stack_size < 2) { 208 return OTS_FAILURE(); 209 } 210 if ((stack_size % 2) == 0) { 211 successful = true; 212 } else if ((!(*in_out_found_width)) && (((stack_size - 1) % 2) == 0)) { 213 // The -1 is for "width" argument. For details, see Adobe Technical Note 214 // #5177, page 16, note 4. 215 successful = true; 216 } 217 (*in_out_num_stems) += (stack_size / 2); 218 if ((*in_out_num_stems) > kMaxNumberOfStemHints) { 219 return OTS_FAILURE(); 220 } 221 while (!argument_stack->empty()) 222 argument_stack->pop(); 223 *in_out_found_width = true; // always set true since "w" might be 0 byte. 224 return successful ? true : OTS_FAILURE(); 225 } 226 227 case ots::kRMoveTo: { 228 bool successful = false; 229 if (stack_size == 2) { 230 successful = true; 231 } else if ((!(*in_out_found_width)) && (stack_size - 1 == 2)) { 232 successful = true; 233 } 234 while (!argument_stack->empty()) 235 argument_stack->pop(); 236 *in_out_found_width = true; 237 return successful ? true : OTS_FAILURE(); 238 } 239 240 case ots::kVMoveTo: 241 case ots::kHMoveTo: { 242 bool successful = false; 243 if (stack_size == 1) { 244 successful = true; 245 } else if ((!(*in_out_found_width)) && (stack_size - 1 == 1)) { 246 successful = true; 247 } 248 while (!argument_stack->empty()) 249 argument_stack->pop(); 250 *in_out_found_width = true; 251 return successful ? true : OTS_FAILURE(); 252 } 253 254 case ots::kHintMask: 255 case ots::kCntrMask: { 256 bool successful = false; 257 if (stack_size == 0) { 258 successful = true; 259 } else if ((!(*in_out_found_width)) && (stack_size == 1)) { 260 // A number for "width" is found. 261 successful = true; 262 } else if ((!(*in_out_found_width)) || // in this case, any sizes are ok. 263 ((stack_size % 2) == 0)) { 264 // The numbers are vstem definition. 265 // See Adobe Technical Note #5177, page 24, hintmask. 266 (*in_out_num_stems) += (stack_size / 2); 267 if ((*in_out_num_stems) > kMaxNumberOfStemHints) { 268 return OTS_FAILURE(); 269 } 270 successful = true; 271 } 272 if (!successful) { 273 return OTS_FAILURE(); 274 } 275 276 if ((*in_out_num_stems) == 0) { 277 return OTS_FAILURE(); 278 } 279 const size_t mask_bytes = (*in_out_num_stems + 7) / 8; 280 if (!char_string->Skip(mask_bytes)) { 281 return OTS_FAILURE(); 282 } 283 while (!argument_stack->empty()) 284 argument_stack->pop(); 285 *in_out_found_width = true; 286 return true; 287 } 288 289 case ots::kRLineTo: 290 if (!(*in_out_found_width)) { 291 // The first stack-clearing operator should be one of hstem, hstemhm, 292 // vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, rmoveto, or 293 // endchar. For details, see Adobe Technical Note #5177, page 16, note 4. 294 return OTS_FAILURE(); 295 } 296 if (stack_size < 2) { 297 return OTS_FAILURE(); 298 } 299 if ((stack_size % 2) != 0) { 300 return OTS_FAILURE(); 301 } 302 while (!argument_stack->empty()) 303 argument_stack->pop(); 304 return true; 305 306 case ots::kHLineTo: 307 case ots::kVLineTo: 308 if (!(*in_out_found_width)) { 309 return OTS_FAILURE(); 310 } 311 if (stack_size < 1) { 312 return OTS_FAILURE(); 313 } 314 while (!argument_stack->empty()) 315 argument_stack->pop(); 316 return true; 317 318 case ots::kRRCurveTo: 319 if (!(*in_out_found_width)) { 320 return OTS_FAILURE(); 321 } 322 if (stack_size < 6) { 323 return OTS_FAILURE(); 324 } 325 if ((stack_size % 6) != 0) { 326 return OTS_FAILURE(); 327 } 328 while (!argument_stack->empty()) 329 argument_stack->pop(); 330 return true; 331 332 case ots::kRCurveLine: 333 if (!(*in_out_found_width)) { 334 return OTS_FAILURE(); 335 } 336 if (stack_size < 8) { 337 return OTS_FAILURE(); 338 } 339 if (((stack_size - 2) % 6) != 0) { 340 return OTS_FAILURE(); 341 } 342 while (!argument_stack->empty()) 343 argument_stack->pop(); 344 return true; 345 346 case ots::kRLineCurve: 347 if (!(*in_out_found_width)) { 348 return OTS_FAILURE(); 349 } 350 if (stack_size < 8) { 351 return OTS_FAILURE(); 352 } 353 if (((stack_size - 6) % 2) != 0) { 354 return OTS_FAILURE(); 355 } 356 while (!argument_stack->empty()) 357 argument_stack->pop(); 358 return true; 359 360 case ots::kVVCurveTo: 361 if (!(*in_out_found_width)) { 362 return OTS_FAILURE(); 363 } 364 if (stack_size < 4) { 365 return OTS_FAILURE(); 366 } 367 if (((stack_size % 4) != 0) && 368 (((stack_size - 1) % 4) != 0)) { 369 return OTS_FAILURE(); 370 } 371 while (!argument_stack->empty()) 372 argument_stack->pop(); 373 return true; 374 375 case ots::kHHCurveTo: { 376 bool successful = false; 377 if (!(*in_out_found_width)) { 378 return OTS_FAILURE(); 379 } 380 if (stack_size < 4) { 381 return OTS_FAILURE(); 382 } 383 if ((stack_size % 4) == 0) { 384 // {dxa dxb dyb dxc}+ 385 successful = true; 386 } else if (((stack_size - 1) % 4) == 0) { 387 // dy1? {dxa dxb dyb dxc}+ 388 successful = true; 389 } 390 while (!argument_stack->empty()) 391 argument_stack->pop(); 392 return successful ? true : OTS_FAILURE(); 393 } 394 395 case ots::kVHCurveTo: 396 case ots::kHVCurveTo: { 397 bool successful = false; 398 if (!(*in_out_found_width)) { 399 return OTS_FAILURE(); 400 } 401 if (stack_size < 4) { 402 return OTS_FAILURE(); 403 } 404 if (((stack_size - 4) % 8) == 0) { 405 // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* 406 successful = true; 407 } else if ((stack_size >= 5) && 408 ((stack_size - 5) % 8) == 0) { 409 // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf 410 successful = true; 411 } else if ((stack_size >= 8) && 412 ((stack_size - 8) % 8) == 0) { 413 // {dxa dxb dyb dyc dyd dxe dye dxf}+ 414 successful = true; 415 } else if ((stack_size >= 9) && 416 ((stack_size - 9) % 8) == 0) { 417 // {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? 418 successful = true; 419 } 420 while (!argument_stack->empty()) 421 argument_stack->pop(); 422 return successful ? true : OTS_FAILURE(); 423 } 424 425 case ots::kAnd: 426 case ots::kOr: 427 case ots::kEq: 428 case ots::kAdd: 429 case ots::kSub: 430 if (stack_size < 2) { 431 return OTS_FAILURE(); 432 } 433 argument_stack->pop(); 434 argument_stack->pop(); 435 argument_stack->push(dummy_result); 436 // TODO(yusukes): Implement this. We should push a real value for all 437 // arithmetic and conditional operations. 438 return true; 439 440 case ots::kNot: 441 case ots::kAbs: 442 case ots::kNeg: 443 if (stack_size < 1) { 444 return OTS_FAILURE(); 445 } 446 argument_stack->pop(); 447 argument_stack->push(dummy_result); 448 // TODO(yusukes): Implement this. We should push a real value for all 449 // arithmetic and conditional operations. 450 return true; 451 452 case ots::kDiv: 453 // TODO(yusukes): Should detect div-by-zero errors. 454 if (stack_size < 2) { 455 return OTS_FAILURE(); 456 } 457 argument_stack->pop(); 458 argument_stack->pop(); 459 argument_stack->push(dummy_result); 460 // TODO(yusukes): Implement this. We should push a real value for all 461 // arithmetic and conditional operations. 462 return true; 463 464 case ots::kDrop: 465 if (stack_size < 1) { 466 return OTS_FAILURE(); 467 } 468 argument_stack->pop(); 469 return true; 470 471 case ots::kPut: 472 case ots::kGet: 473 case ots::kIndex: 474 // For now, just call OTS_FAILURE since there is no way to check whether the 475 // index argument, |i|, is out-of-bounds or not. Fortunately, no OpenType 476 // fonts I have (except malicious ones!) use the operators. 477 // TODO(yusukes): Implement them in a secure way. 478 return OTS_FAILURE(); 479 480 case ots::kRoll: 481 // Likewise, just call OTS_FAILURE for kRoll since there is no way to check 482 // whether |N| is smaller than the current stack depth or not. 483 // TODO(yusukes): Implement them in a secure way. 484 return OTS_FAILURE(); 485 486 case ots::kRandom: 487 // For now, we don't handle the 'random' operator since the operator makes 488 // it hard to analyze hinting code statically. 489 return OTS_FAILURE(); 490 491 case ots::kIfElse: 492 if (stack_size < 4) { 493 return OTS_FAILURE(); 494 } 495 argument_stack->pop(); 496 argument_stack->pop(); 497 argument_stack->pop(); 498 argument_stack->pop(); 499 argument_stack->push(dummy_result); 500 // TODO(yusukes): Implement this. We should push a real value for all 501 // arithmetic and conditional operations. 502 return true; 503 504 case ots::kMul: 505 // TODO(yusukes): Should detect overflows. 506 if (stack_size < 2) { 507 return OTS_FAILURE(); 508 } 509 argument_stack->pop(); 510 argument_stack->pop(); 511 argument_stack->push(dummy_result); 512 // TODO(yusukes): Implement this. We should push a real value for all 513 // arithmetic and conditional operations. 514 return true; 515 516 case ots::kSqrt: 517 // TODO(yusukes): Should check if the argument is negative. 518 if (stack_size < 1) { 519 return OTS_FAILURE(); 520 } 521 argument_stack->pop(); 522 argument_stack->push(dummy_result); 523 // TODO(yusukes): Implement this. We should push a real value for all 524 // arithmetic and conditional operations. 525 return true; 526 527 case ots::kDup: 528 if (stack_size < 1) { 529 return OTS_FAILURE(); 530 } 531 argument_stack->pop(); 532 argument_stack->push(dummy_result); 533 argument_stack->push(dummy_result); 534 if (argument_stack->size() > kMaxArgumentStack) { 535 return OTS_FAILURE(); 536 } 537 // TODO(yusukes): Implement this. We should push a real value for all 538 // arithmetic and conditional operations. 539 return true; 540 541 case ots::kExch: 542 if (stack_size < 2) { 543 return OTS_FAILURE(); 544 } 545 argument_stack->pop(); 546 argument_stack->pop(); 547 argument_stack->push(dummy_result); 548 argument_stack->push(dummy_result); 549 // TODO(yusukes): Implement this. We should push a real value for all 550 // arithmetic and conditional operations. 551 return true; 552 553 case ots::kHFlex: 554 if (!(*in_out_found_width)) { 555 return OTS_FAILURE(); 556 } 557 if (stack_size != 7) { 558 return OTS_FAILURE(); 559 } 560 while (!argument_stack->empty()) 561 argument_stack->pop(); 562 return true; 563 564 case ots::kFlex: 565 if (!(*in_out_found_width)) { 566 return OTS_FAILURE(); 567 } 568 if (stack_size != 13) { 569 return OTS_FAILURE(); 570 } 571 while (!argument_stack->empty()) 572 argument_stack->pop(); 573 return true; 574 575 case ots::kHFlex1: 576 if (!(*in_out_found_width)) { 577 return OTS_FAILURE(); 578 } 579 if (stack_size != 9) { 580 return OTS_FAILURE(); 581 } 582 while (!argument_stack->empty()) 583 argument_stack->pop(); 584 return true; 585 586 case ots::kFlex1: 587 if (!(*in_out_found_width)) { 588 return OTS_FAILURE(); 589 } 590 if (stack_size != 11) { 591 return OTS_FAILURE(); 592 } 593 while (!argument_stack->empty()) 594 argument_stack->pop(); 595 return true; 596 } 597 598 OTS_WARNING("Undefined operator: %d (0x%x)", op, op); 599 return OTS_FAILURE(); 600 } 601 602 // Executes |char_string| and updates |argument_stack|. 603 // 604 // call_depth: The current call depth. Initial value is zero. 605 // global_subrs_index: Global subroutines. 606 // local_subrs_index: Local subroutines for the current glyph. 607 // cff_table: A whole CFF table which contains all global and local subroutines. 608 // char_string: A charstring we'll execute. |char_string| can be a main routine 609 // in CharString INDEX, or a subroutine in GlobalSubr/LocalSubr. 610 // argument_stack: The stack which an operator in |char_string| operates. 611 // out_found_endchar: true is set if |char_string| contains 'endchar'. 612 // in_out_found_width: true is set if |char_string| contains 'width' byte (which 613 // is 0 or 1 byte.) 614 // in_out_num_stems: total number of hstems and vstems processed so far. 615 bool ExecuteType2CharString(size_t call_depth, 616 const ots::CFFIndex& global_subrs_index, 617 const ots::CFFIndex& local_subrs_index, 618 ots::Buffer *cff_table, 619 ots::Buffer *char_string, 620 std::stack<int32_t> *argument_stack, 621 bool *out_found_endchar, 622 bool *in_out_found_width, 623 size_t *in_out_num_stems) { 624 if (call_depth > kMaxSubrNesting) { 625 return OTS_FAILURE(); 626 } 627 *out_found_endchar = false; 628 629 const size_t length = char_string->length(); 630 while (char_string->offset() < length) { 631 int32_t operator_or_operand = 0; 632 bool is_operator = false; 633 if (!ReadNextNumberFromType2CharString(char_string, 634 &operator_or_operand, 635 &is_operator)) { 636 return OTS_FAILURE(); 637 } 638 639 /* 640 You can dump all operators and operands (except mask bytes for hintmask 641 and cntrmask) by the following code: 642 643 if (!is_operator) { 644 std::fprintf(stderr, "#%d# ", operator_or_operand); 645 } else { 646 std::fprintf(stderr, "#%s#\n", 647 Type2CharStringOperatorToString( 648 Type2CharStringOperator(operator_or_operand)), 649 operator_or_operand); 650 } 651 */ 652 653 if (!is_operator) { 654 argument_stack->push(operator_or_operand); 655 if (argument_stack->size() > kMaxArgumentStack) { 656 return OTS_FAILURE(); 657 } 658 continue; 659 } 660 661 // An operator is found. Execute it. 662 if (!ExecuteType2CharStringOperator(operator_or_operand, 663 call_depth, 664 global_subrs_index, 665 local_subrs_index, 666 cff_table, 667 char_string, 668 argument_stack, 669 out_found_endchar, 670 in_out_found_width, 671 in_out_num_stems)) { 672 return OTS_FAILURE(); 673 } 674 if (*out_found_endchar) { 675 return true; 676 } 677 if (operator_or_operand == ots::kReturn) { 678 return true; 679 } 680 } 681 682 // No endchar operator is found. 683 return OTS_FAILURE(); 684 } 685 686 // Selects a set of subroutings for |glyph_index| from |cff| and sets it on 687 // |out_local_subrs_to_use|. Returns true on success. 688 bool SelectLocalSubr(const std::map<uint16_t, uint8_t> &fd_select, 689 const std::vector<ots::CFFIndex *> &local_subrs_per_font, 690 const ots::CFFIndex *local_subrs, 691 uint16_t glyph_index, // 0-origin 692 const ots::CFFIndex **out_local_subrs_to_use) { 693 *out_local_subrs_to_use = NULL; 694 695 // First, find local subrs from |local_subrs_per_font|. 696 if ((fd_select.size() > 0) && 697 (!local_subrs_per_font.empty())) { 698 // Look up FDArray index for the glyph. 699 std::map<uint16_t, uint8_t>::const_iterator iter = 700 fd_select.find(glyph_index); 701 if (iter == fd_select.end()) { 702 return OTS_FAILURE(); 703 } 704 const uint8_t fd_index = iter->second; 705 if (fd_index >= local_subrs_per_font.size()) { 706 return OTS_FAILURE(); 707 } 708 *out_local_subrs_to_use = local_subrs_per_font.at(fd_index); 709 } else if (local_subrs) { 710 // Second, try to use |local_subrs|. Most Latin fonts don't have FDSelect 711 // entries. If The font has a local subrs index associated with the Top 712 // DICT (not FDArrays), use it. 713 *out_local_subrs_to_use = local_subrs; 714 } else { 715 // Just return NULL. 716 *out_local_subrs_to_use = NULL; 717 } 718 719 return true; 720 } 721 722 } // namespace 723 724 namespace ots { 725 726 bool ValidateType2CharStringIndex( 727 const CFFIndex& char_strings_index, 728 const CFFIndex& global_subrs_index, 729 const std::map<uint16_t, uint8_t> &fd_select, 730 const std::vector<CFFIndex *> &local_subrs_per_font, 731 const CFFIndex *local_subrs, 732 Buffer* cff_table) { 733 if (char_strings_index.offsets.size() == 0) { 734 return OTS_FAILURE(); // no charstring. 735 } 736 737 // For each glyph, validate the corresponding charstring. 738 for (unsigned i = 1; i < char_strings_index.offsets.size(); ++i) { 739 // Prepare a Buffer object, |char_string|, which contains the charstring 740 // for the |i|-th glyph. 741 const size_t length = 742 char_strings_index.offsets[i] - char_strings_index.offsets[i - 1]; 743 if (length > kMaxCharStringLength) { 744 return OTS_FAILURE(); 745 } 746 const size_t offset = char_strings_index.offsets[i - 1]; 747 cff_table->set_offset(offset); 748 if (!cff_table->Skip(length)) { 749 return OTS_FAILURE(); 750 } 751 Buffer char_string(cff_table->buffer() + offset, length); 752 753 // Get a local subrs for the glyph. 754 const unsigned glyph_index = i - 1; // index in the map is 0-origin. 755 const CFFIndex *local_subrs_to_use = NULL; 756 if (!SelectLocalSubr(fd_select, 757 local_subrs_per_font, 758 local_subrs, 759 glyph_index, 760 &local_subrs_to_use)) { 761 return OTS_FAILURE(); 762 } 763 // If |local_subrs_to_use| is still NULL, use an empty one. 764 CFFIndex default_empty_subrs; 765 if (!local_subrs_to_use){ 766 local_subrs_to_use = &default_empty_subrs; 767 } 768 769 // Check a charstring for the |i|-th glyph. 770 std::stack<int32_t> argument_stack; 771 bool found_endchar = false; 772 bool found_width = false; 773 size_t num_stems = 0; 774 if (!ExecuteType2CharString(0 /* initial call_depth is zero */, 775 global_subrs_index, *local_subrs_to_use, 776 cff_table, &char_string, &argument_stack, 777 &found_endchar, &found_width, &num_stems)) { 778 return OTS_FAILURE(); 779 } 780 if (!found_endchar) { 781 return OTS_FAILURE(); 782 } 783 } 784 return true; 785 } 786 787 } // namespace ots 788