• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ReadNextNumberFromType2CharString(ots::Buffer * char_string,int32_t * out_number,bool * out_is_operator)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.
ExecuteType2CharStringOperator(int32_t op,size_t call_depth,const ots::CFFIndex & global_subrs_index,const ots::CFFIndex & local_subrs_index,ots::Buffer * cff_table,ots::Buffer * char_string,std::stack<int32_t> * argument_stack,bool * out_found_endchar,bool * in_out_found_width,size_t * in_out_num_stems)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.
ExecuteType2CharString(size_t call_depth,const ots::CFFIndex & global_subrs_index,const ots::CFFIndex & local_subrs_index,ots::Buffer * cff_table,ots::Buffer * char_string,std::stack<int32_t> * argument_stack,bool * out_found_endchar,bool * in_out_found_width,size_t * in_out_num_stems)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.
SelectLocalSubr(const std::map<uint16_t,uint8_t> & fd_select,const std::vector<ots::CFFIndex * > & local_subrs_per_font,const ots::CFFIndex * local_subrs,uint16_t glyph_index,const ots::CFFIndex ** out_local_subrs_to_use)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 
ValidateType2CharStringIndex(const CFFIndex & char_strings_index,const CFFIndex & global_subrs_index,const std::map<uint16_t,uint8_t> & fd_select,const std::vector<CFFIndex * > & local_subrs_per_font,const CFFIndex * local_subrs,Buffer * cff_table)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