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