Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ots/src/cff_charstring.cc
Line
Count
Source
1
// Copyright (c) 2010-2017 The OTS 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_charstring.h"
9
10
#include <climits>
11
#include <cstdio>
12
#include <cstring>
13
#include <stack>
14
#include <string>
15
#include <utility>
16
17
#define TABLE_NAME "CFF"
18
19
namespace {
20
21
// Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical
22
// Note #5177.
23
const int32_t kMaxSubrsCount = 65536;
24
const size_t kMaxCharStringLength = 65535;
25
const size_t kMaxNumberOfStemHints = 96;
26
const size_t kMaxSubrNesting = 10;
27
28
// |dummy_result| should be a huge positive integer so callsubr and callgsubr
29
// will fail with the dummy value.
30
const int32_t dummy_result = INT_MAX;
31
32
bool ExecuteCharString(ots::OpenTypeCFF& cff,
33
                       size_t call_depth,
34
                       const ots::CFFIndex& global_subrs_index,
35
                       const ots::CFFIndex& local_subrs_index,
36
                       ots::Buffer *cff_table,
37
                       ots::Buffer *char_string,
38
                       std::stack<int32_t> *argument_stack,
39
                       ots::CharStringContext& cs_ctx);
40
41
4.38M
bool ArgumentStackOverflows(std::stack<int32_t> *argument_stack, bool cff2) {
42
4.38M
  if ((cff2 && argument_stack->size() > ots::kMaxCFF2ArgumentStack) ||
43
4.38M
      (!cff2 && argument_stack->size() > ots::kMaxCFF1ArgumentStack)) {
44
16
    return true;
45
16
  }
46
4.38M
  return false;
47
4.38M
}
48
49
#ifdef DUMP_T2CHARSTRING
50
// Converts |op| to a string and returns it.
51
const char *CharStringOperatorToString(ots::CharStringOperator op) {
52
  switch (op) {
53
  case ots::kHStem:
54
    return "hstem";
55
  case ots::kVStem:
56
    return "vstem";
57
  case ots::kVMoveTo:
58
    return "vmoveto";
59
  case ots::kRLineTo:
60
    return "rlineto";
61
  case ots::kHLineTo:
62
    return "hlineto";
63
  case ots::kVLineTo:
64
    return "vlineto";
65
  case ots::kRRCurveTo:
66
    return "rrcurveto";
67
  case ots::kCallSubr:
68
    return "callsubr";
69
  case ots::kReturn:
70
    return "return";
71
  case ots::kEndChar:
72
    return "endchar";
73
  case ots::kVSIndex:
74
    return "vsindex";
75
  case ots::kBlend:
76
    return "blend";
77
  case ots::kHStemHm:
78
    return "hstemhm";
79
  case ots::kHintMask:
80
    return "hintmask";
81
  case ots::kCntrMask:
82
    return "cntrmask";
83
  case ots::kRMoveTo:
84
    return "rmoveto";
85
  case ots::kHMoveTo:
86
    return "hmoveto";
87
  case ots::kVStemHm:
88
    return "vstemhm";
89
  case ots::kRCurveLine:
90
    return "rcurveline";
91
  case ots::kRLineCurve:
92
    return "rlinecurve";
93
  case ots::kVVCurveTo:
94
    return "VVCurveTo";
95
  case ots::kHHCurveTo:
96
    return "hhcurveto";
97
  case ots::kCallGSubr:
98
    return "callgsubr";
99
  case ots::kVHCurveTo:
100
    return "vhcurveto";
101
  case ots::kHVCurveTo:
102
    return "HVCurveTo";
103
  case ots::kDotSection:
104
    return "dotsection";
105
  case ots::kAnd:
106
    return "and";
107
  case ots::kOr:
108
    return "or";
109
  case ots::kNot:
110
    return "not";
111
  case ots::kAbs:
112
    return "abs";
113
  case ots::kAdd:
114
    return "add";
115
  case ots::kSub:
116
    return "sub";
117
  case ots::kDiv:
118
    return "div";
119
  case ots::kNeg:
120
    return "neg";
121
  case ots::kEq:
122
    return "eq";
123
  case ots::kDrop:
124
    return "drop";
125
  case ots::kPut:
126
    return "put";
127
  case ots::kGet:
128
    return "get";
129
  case ots::kIfElse:
130
    return "ifelse";
131
  case ots::kRandom:
132
    return "random";
133
  case ots::kMul:
134
    return "mul";
135
  case ots::kSqrt:
136
    return "sqrt";
137
  case ots::kDup:
138
    return "dup";
139
  case ots::kExch:
140
    return "exch";
141
  case ots::kIndex:
142
    return "index";
143
  case ots::kRoll:
144
    return "roll";
145
  case ots::kHFlex:
146
    return "hflex";
147
  case ots::kFlex:
148
    return "flex";
149
  case ots::kHFlex1:
150
    return "hflex1";
151
  case ots::kFlex1:
152
    return "flex1";
153
  }
154
155
  return "UNKNOWN";
156
}
157
#endif
158
159
// Read one or more bytes from the |char_string| buffer and stores the number
160
// read on |out_number|. If the number read is an operator (ex 'vstem'), sets
161
// true on |out_is_operator|. Returns true if the function read a number.
162
bool ReadNextNumberFromCharString(ots::Buffer *char_string,
163
                                  int32_t *out_number,
164
5.41M
                                  bool *out_is_operator) {
165
5.41M
  uint8_t v = 0;
166
5.41M
  if (!char_string->ReadU8(&v)) {
167
0
    return OTS_FAILURE();
168
0
  }
169
5.41M
  *out_is_operator = false;
170
171
  // The conversion algorithm is described in Adobe Technical Note #5177, page
172
  // 13, Table 1.
173
5.41M
  if (v <= 11) {
174
486k
    *out_number = v;
175
486k
    *out_is_operator = true;
176
4.93M
  } else if (v == 12) {
177
1.75k
    uint16_t result = (v << 8);
178
1.75k
    if (!char_string->ReadU8(&v)) {
179
1
      return OTS_FAILURE();
180
1
    }
181
1.75k
    result += v;
182
1.75k
    *out_number = result;
183
1.75k
    *out_is_operator = true;
184
4.92M
  } else if (v <= 27) {
185
    // Special handling for v==19 and v==20 are implemented in
186
    // ExecuteCharStringOperator().
187
363k
    *out_number = v;
188
363k
    *out_is_operator = true;
189
4.56M
  } else if (v == 28) {
190
55.3k
    if (!char_string->ReadU8(&v)) {
191
1
      return OTS_FAILURE();
192
1
    }
193
55.3k
    uint16_t result = (v << 8);
194
55.3k
    if (!char_string->ReadU8(&v)) {
195
2
      return OTS_FAILURE();
196
2
    }
197
55.3k
    result += v;
198
55.3k
    *out_number = static_cast<int16_t>(result);
199
4.50M
  } else if (v <= 31) {
200
176k
    *out_number = v;
201
176k
    *out_is_operator = true;
202
4.33M
  } else if (v <= 246) {
203
3.48M
    *out_number = static_cast<int32_t>(v) - 139;
204
3.48M
  } else if (v <= 250) {
205
462k
    uint8_t w = 0;
206
462k
    if (!char_string->ReadU8(&w)) {
207
1
      return OTS_FAILURE();
208
1
    }
209
462k
    *out_number = ((static_cast<int32_t>(v) - 247) * 256) +
210
462k
        static_cast<int32_t>(w) + 108;
211
462k
  } else if (v <= 254) {
212
381k
    uint8_t w = 0;
213
381k
    if (!char_string->ReadU8(&w)) {
214
2
      return OTS_FAILURE();
215
2
    }
216
381k
    *out_number = -((static_cast<int32_t>(v) - 251) * 256) -
217
381k
        static_cast<int32_t>(w) - 108;
218
381k
  } else if (v == 255) {
219
    // TODO(yusukes): We should not skip the 4 bytes. Note that when v is 255,
220
    // we should treat the following 4-bytes as a 16.16 fixed-point number
221
    // rather than 32bit signed int.
222
1.55k
    if (!char_string->Skip(4)) {
223
4
      return OTS_FAILURE();
224
4
    }
225
1.54k
    *out_number = dummy_result;
226
1.54k
  } else {
227
0
    return OTS_FAILURE();
228
0
  }
229
230
5.41M
  return true;
231
5.41M
}
232
233
732k
bool ValidCFF2Operator(int32_t op) {
234
732k
  switch (op) {
235
1
  case ots::kReturn:
236
7
  case ots::kEndChar:
237
8
  case ots::kAbs:
238
8
  case ots::kAdd:
239
11
  case ots::kSub:
240
12
  case ots::kDiv:
241
13
  case ots::kNeg:
242
13
  case ots::kRandom:
243
14
  case ots::kMul:
244
15
  case ots::kSqrt:
245
16
  case ots::kDrop:
246
17
  case ots::kExch:
247
18
  case ots::kIndex:
248
19
  case ots::kRoll:
249
20
  case ots::kDup:
250
21
  case ots::kPut:
251
23
  case ots::kGet:
252
24
  case ots::kDotSection:
253
25
  case ots::kAnd:
254
26
  case ots::kOr:
255
27
  case ots::kNot:
256
28
  case ots::kEq:
257
29
  case ots::kIfElse:
258
29
    return false;
259
732k
  }
260
261
732k
  return true;
262
732k
}
263
264
// Executes |op| and updates |argument_stack|. Returns true if the execution
265
// succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively
266
// calls ExecuteCharString() function. The |cs_ctx| argument holds values that
267
// need to persist through these calls (see CharStringContext for details)
268
bool ExecuteCharStringOperator(ots::OpenTypeCFF& cff,
269
                               int32_t op,
270
                               size_t call_depth,
271
                               const ots::CFFIndex& global_subrs_index,
272
                               const ots::CFFIndex& local_subrs_index,
273
                               ots::Buffer *cff_table,
274
                               ots::Buffer *char_string,
275
                               std::stack<int32_t> *argument_stack,
276
1.02M
                               ots::CharStringContext& cs_ctx) {
277
1.02M
  ots::Font* font = cff.GetFont();
278
1.02M
  const size_t stack_size = argument_stack->size();
279
280
1.02M
  if (cs_ctx.cff2 && !ValidCFF2Operator(op)) {
281
29
    return OTS_FAILURE();
282
29
  }
283
284
1.02M
  switch (op) {
285
172k
  case ots::kCallSubr:
286
185k
  case ots::kCallGSubr: {
287
185k
    const ots::CFFIndex& subrs_index =
288
185k
        (op == ots::kCallSubr ? local_subrs_index : global_subrs_index);
289
290
185k
    if (stack_size < 1) {
291
4
      return OTS_FAILURE();
292
4
    }
293
185k
    int32_t subr_number = argument_stack->top();
294
185k
    argument_stack->pop();
295
185k
    if (subr_number == dummy_result) {
296
      // For safety, we allow subr calls only with immediate subr numbers for
297
      // now. For example, we allow "123 callgsubr", but does not allow "100 12
298
      // add callgsubr". Please note that arithmetic and conditional operators
299
      // always push the |dummy_result| in this implementation.
300
1
      return OTS_FAILURE();
301
1
    }
302
303
    // See Adobe Technical Note #5176 (CFF), "16. Local/GlobalSubrs INDEXes."
304
185k
    int32_t bias = 32768;
305
185k
    if (subrs_index.count < 1240) {
306
92.8k
      bias = 107;
307
92.8k
    } else if (subrs_index.count < 33900) {
308
92.6k
      bias = 1131;
309
92.6k
    }
310
185k
    subr_number += bias;
311
312
    // Sanity checks of |subr_number|.
313
185k
    if (subr_number < 0) {
314
7
      return OTS_FAILURE();
315
7
    }
316
185k
    if (subr_number >= kMaxSubrsCount) {
317
0
      return OTS_FAILURE();
318
0
    }
319
185k
    if (subrs_index.offsets.size() <= static_cast<size_t>(subr_number + 1)) {
320
14
      return OTS_FAILURE();  // The number is out-of-bounds.
321
14
    }
322
323
    // Prepare ots::Buffer where we're going to jump.
324
185k
    const size_t length =
325
185k
      subrs_index.offsets[subr_number + 1] - subrs_index.offsets[subr_number];
326
185k
    if (length > kMaxCharStringLength) {
327
0
      return OTS_FAILURE();
328
0
    }
329
185k
    const size_t offset = subrs_index.offsets[subr_number];
330
185k
    cff_table->set_offset(offset);
331
185k
    if (!cff_table->Skip(length)) {
332
0
      return OTS_FAILURE();
333
0
    }
334
185k
    ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length);
335
336
185k
    return ExecuteCharString(cff,
337
185k
                             call_depth + 1,
338
185k
                             global_subrs_index,
339
185k
                             local_subrs_index,
340
185k
                             cff_table,
341
185k
                             &char_string_to_jump,
342
185k
                             argument_stack,
343
185k
                             cs_ctx);
344
185k
  }
345
346
43.6k
  case ots::kReturn:
347
43.6k
    return true;
348
349
19.1k
  case ots::kEndChar:
350
19.1k
    cs_ctx.endchar_seen = true;
351
19.1k
    cs_ctx.width_seen = true;  // just in case.
352
19.1k
    return true;
353
354
579
  case ots::kVSIndex: {
355
579
    if (!cs_ctx.cff2) {
356
2
      return OTS_FAILURE();
357
2
    }
358
577
    if (stack_size != 1) {
359
2
      return OTS_FAILURE();
360
2
    }
361
575
    if (cs_ctx.blend_seen || cs_ctx.vsindex_seen) {
362
3
      return OTS_FAILURE();
363
3
    }
364
572
    if (argument_stack->top() < 0 ||
365
565
        argument_stack->top() >= (int32_t)cff.region_index_count.size()) {
366
9
      return OTS_FAILURE();
367
9
    }
368
563
    cs_ctx.vsindex_seen = true;
369
563
    cs_ctx.vsindex = argument_stack->top();
370
1.12k
    while (!argument_stack->empty())
371
563
      argument_stack->pop();
372
563
    return true;
373
572
  }
374
375
97.9k
  case ots::kBlend: {
376
97.9k
    if (!cs_ctx.cff2) {
377
1
      return OTS_FAILURE();
378
1
    }
379
97.9k
    if (stack_size < 1) {
380
1
      return OTS_FAILURE();
381
1
    }
382
97.9k
    if (cs_ctx.vsindex >= (int32_t)cff.region_index_count.size()) {
383
0
      return OTS_FAILURE();
384
0
    }
385
97.9k
    uint16_t k = cff.region_index_count.at(cs_ctx.vsindex);
386
97.9k
    uint16_t n = argument_stack->top();
387
97.9k
    if (stack_size < n * (k + 1u) + 1u) {
388
8
      return OTS_FAILURE();
389
8
    }
390
391
    // Keep the 1st n operands on the stack for the next operator to use and
392
    // pop the rest. There can be multiple consecutive blend operators, so this
393
    // makes sure the operands of all of them are kept on the stack.
394
871k
    while (argument_stack->size() > stack_size - ((n * k) + 1))
395
773k
      argument_stack->pop();
396
97.9k
    cs_ctx.blend_seen = true;
397
97.9k
    return true;
398
97.9k
  }
399
400
381
  case ots::kHStem:
401
858
  case ots::kVStem:
402
1.25k
  case ots::kHStemHm:
403
1.35k
  case ots::kVStemHm: {
404
1.35k
    bool successful = false;
405
1.35k
    if (stack_size < 2) {
406
8
      return OTS_FAILURE();
407
8
    }
408
1.34k
    if (op == ots::kHStem || op == ots::kHStemHm) {
409
773
      if (cs_ctx.hint_state > ots::kHs) {
410
6
        return OTS_FAILURE();
411
6
      }
412
773
    } else {
413
571
      if (cs_ctx.hint_state > ots::kVs) {
414
3
        return OTS_FAILURE();
415
3
      }
416
568
      cs_ctx.hint_state = ots::kVs;
417
568
    }
418
1.33k
    if ((stack_size % 2) == 0) {
419
885
      successful = true;
420
885
    } else if ((!(cs_ctx.width_seen)) && (((stack_size - 1) % 2) == 0)) {
421
      // The -1 is for "width" argument. For details, see Adobe Technical Note
422
      // #5177, page 16, note 4.
423
447
      successful = true;
424
447
    }
425
1.33k
    cs_ctx.num_stems += (stack_size / 2);
426
1.33k
    if ((cs_ctx.num_stems) > kMaxNumberOfStemHints) {
427
6
      return OTS_FAILURE();
428
6
    }
429
9.84k
    while (!argument_stack->empty())
430
8.52k
      argument_stack->pop();
431
1.32k
    cs_ctx.width_seen = true;  // always set true since "w" might be 0 byte.
432
1.32k
    return successful ? true : OTS_FAILURE();
433
1.33k
  }
434
435
101k
  case ots::kRMoveTo: {
436
101k
    bool successful = false;
437
101k
    if (stack_size == 2) {
438
87.2k
      successful = true;
439
87.2k
    } else if ((!(cs_ctx.width_seen)) && (stack_size - 1 == 2)) {
440
14.7k
      successful = true;
441
14.7k
    }
442
320k
    while (!argument_stack->empty())
443
218k
      argument_stack->pop();
444
101k
    cs_ctx.width_seen = true;
445
101k
    cs_ctx.hint_state = ots::kHm;
446
101k
    return successful ? true : OTS_FAILURE();
447
1.33k
  }
448
449
3.51k
  case ots::kVMoveTo:
450
15.7k
  case ots::kHMoveTo: {
451
15.7k
    bool successful = false;
452
15.7k
    if (stack_size == 1) {
453
13.2k
      successful = true;
454
13.2k
    } else if ((!(cs_ctx.width_seen)) && (stack_size - 1 == 1)) {
455
2.48k
      successful = true;
456
2.48k
    }
457
34.0k
    while (!argument_stack->empty())
458
18.3k
      argument_stack->pop();
459
15.7k
    cs_ctx.width_seen = true;
460
15.7k
    cs_ctx.hint_state = ots::kHm;
461
15.7k
    return successful ? true : OTS_FAILURE();
462
3.51k
  }
463
464
890
  case ots::kHintMask:
465
1.21k
  case ots::kCntrMask: {
466
1.21k
    bool successful = false;
467
1.21k
    if (stack_size == 0) {
468
825
      successful = true;
469
825
    } else if ((!(cs_ctx.width_seen)) && (stack_size == 1)) {
470
      // A number for "width" is found.
471
1
      successful = true;
472
389
    } else if ((!(cs_ctx.width_seen)) ||  // in this case, any sizes are ok.
473
385
               ((stack_size % 2) == 0)) {
474
      // The numbers are vstem definition.
475
      // See Adobe Technical Note #5177, page 24, hintmask.
476
385
      cs_ctx.num_stems += (stack_size / 2);
477
385
      if ((cs_ctx.num_stems) > kMaxNumberOfStemHints) {
478
1
        return OTS_FAILURE();
479
1
      }
480
384
      successful = true;
481
384
    }
482
1.21k
    if (!successful) {
483
4
       return OTS_FAILURE();
484
4
    }
485
1.21k
    if (op == ots::kHintMask) {
486
888
      cs_ctx.hint_state = ots::kHm;
487
888
    } else {
488
322
      if (cs_ctx.hint_state > ots::kCm) {
489
1
        return OTS_FAILURE();
490
1
      }
491
321
      cs_ctx.hint_state = ots::kCm;
492
321
    }
493
1.20k
    if ((cs_ctx.num_stems) == 0) {
494
1
      return OTS_FAILURE();
495
1
    }
496
1.20k
    const size_t mask_bytes = (cs_ctx.num_stems + 7) / 8;
497
1.20k
    if (!char_string->Skip(mask_bytes)) {
498
2
      return OTS_FAILURE();
499
2
    }
500
3.68k
    while (!argument_stack->empty())
501
2.47k
      argument_stack->pop();
502
1.20k
    cs_ctx.width_seen = true;
503
1.20k
    return true;
504
1.20k
  }
505
506
81.2k
  case ots::kRLineTo:
507
81.2k
    if (!(cs_ctx.width_seen)) {
508
      // The first stack-clearing operator should be one of hstem, hstemhm,
509
      // vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, rmoveto, or
510
      // endchar. For details, see Adobe Technical Note #5177, page 16, note 4.
511
1
      return OTS_FAILURE();
512
1
    }
513
81.2k
    if (stack_size < 2) {
514
4
      return OTS_FAILURE();
515
4
    }
516
81.2k
    if ((stack_size % 2) != 0) {
517
2
      return OTS_FAILURE();
518
2
    }
519
419k
    while (!argument_stack->empty())
520
338k
      argument_stack->pop();
521
81.2k
    return true;
522
523
81.9k
  case ots::kHLineTo:
524
131k
  case ots::kVLineTo:
525
131k
    if (!(cs_ctx.width_seen)) {
526
1
      return OTS_FAILURE();
527
1
    }
528
131k
    if (stack_size < 1) {
529
2
      return OTS_FAILURE();
530
2
    }
531
356k
    while (!argument_stack->empty())
532
225k
      argument_stack->pop();
533
131k
    return true;
534
535
53.8k
  case ots::kRRCurveTo:
536
53.8k
    if (!(cs_ctx.width_seen)) {
537
1
      return OTS_FAILURE();
538
1
    }
539
53.8k
    if (stack_size < 6) {
540
4
      return OTS_FAILURE();
541
4
    }
542
53.8k
    if ((stack_size % 6) != 0) {
543
6
      return OTS_FAILURE();
544
6
    }
545
795k
    while (!argument_stack->empty())
546
741k
      argument_stack->pop();
547
53.8k
    return true;
548
549
13.0k
  case ots::kRCurveLine:
550
13.0k
    if (!(cs_ctx.width_seen)) {
551
1
      return OTS_FAILURE();
552
1
    }
553
13.0k
    if (stack_size < 8) {
554
3
      return OTS_FAILURE();
555
3
    }
556
13.0k
    if (((stack_size - 2) % 6) != 0) {
557
3
      return OTS_FAILURE();
558
3
    }
559
152k
    while (!argument_stack->empty())
560
139k
      argument_stack->pop();
561
13.0k
    return true;
562
563
11.3k
  case ots::kRLineCurve:
564
11.3k
    if (!(cs_ctx.width_seen)) {
565
1
      return OTS_FAILURE();
566
1
    }
567
11.3k
    if (stack_size < 8) {
568
1
      return OTS_FAILURE();
569
1
    }
570
11.3k
    if (((stack_size - 6) % 2) != 0) {
571
1
      return OTS_FAILURE();
572
1
    }
573
116k
    while (!argument_stack->empty())
574
104k
      argument_stack->pop();
575
11.3k
    return true;
576
577
50.4k
  case ots::kVVCurveTo:
578
50.4k
    if (!(cs_ctx.width_seen)) {
579
1
      return OTS_FAILURE();
580
1
    }
581
50.4k
    if (stack_size < 4) {
582
2
      return OTS_FAILURE();
583
2
    }
584
50.4k
    if (((stack_size % 4) != 0) &&
585
45.3k
        (((stack_size - 1) % 4) != 0)) {
586
1
      return OTS_FAILURE();
587
1
    }
588
303k
    while (!argument_stack->empty())
589
253k
      argument_stack->pop();
590
50.4k
    return true;
591
592
55.2k
  case ots::kHHCurveTo: {
593
55.2k
    bool successful = false;
594
55.2k
    if (!(cs_ctx.width_seen)) {
595
2
      return OTS_FAILURE();
596
2
    }
597
55.2k
    if (stack_size < 4) {
598
3
      return OTS_FAILURE();
599
3
    }
600
55.2k
    if ((stack_size % 4) == 0) {
601
      // {dxa dxb dyb dxc}+
602
5.54k
      successful = true;
603
49.7k
    } else if (((stack_size - 1) % 4) == 0) {
604
      // dy1? {dxa dxb dyb dxc}+
605
49.7k
      successful = true;
606
49.7k
    }
607
343k
    while (!argument_stack->empty())
608
287k
      argument_stack->pop();
609
55.2k
    return successful ? true : OTS_FAILURE();
610
55.2k
  }
611
612
85.8k
  case ots::kVHCurveTo:
613
163k
  case ots::kHVCurveTo: {
614
163k
    bool successful = false;
615
163k
    if (!(cs_ctx.width_seen)) {
616
1
      return OTS_FAILURE();
617
1
    }
618
163k
    if (stack_size < 4) {
619
3
      return OTS_FAILURE();
620
3
    }
621
163k
    if (((stack_size - 4) % 8) == 0) {
622
      // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}*
623
38.0k
      successful = true;
624
125k
    } else if ((stack_size >= 5) &&
625
125k
               ((stack_size - 5) % 8) == 0) {
626
      // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf
627
82.6k
      successful = true;
628
82.6k
    } else if ((stack_size >= 8) &&
629
42.4k
               ((stack_size - 8) % 8) == 0) {
630
      // {dxa dxb dyb dyc dyd dxe dye dxf}+
631
27.6k
      successful = true;
632
27.6k
    } else if ((stack_size >= 9) &&
633
14.8k
               ((stack_size - 9) % 8) == 0) {
634
      // {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
635
14.8k
      successful = true;
636
14.8k
    }
637
1.23M
    while (!argument_stack->empty())
638
1.07M
      argument_stack->pop();
639
163k
    return successful ? true : OTS_FAILURE();
640
163k
  }
641
642
37
  case ots::kDotSection:
643
    // Deprecated operator but harmless, we probably should drop it some how.
644
37
    if (stack_size != 0) {
645
1
      return OTS_FAILURE();
646
1
    }
647
36
    return true;
648
649
40
  case ots::kAnd:
650
146
  case ots::kOr:
651
179
  case ots::kEq:
652
230
  case ots::kAdd:
653
276
  case ots::kSub:
654
276
    if (stack_size < 2) {
655
1
      return OTS_FAILURE();
656
1
    }
657
275
    argument_stack->pop();
658
275
    argument_stack->pop();
659
275
    argument_stack->push(dummy_result);
660
    // TODO(yusukes): Implement this. We should push a real value for all
661
    // arithmetic and conditional operations.
662
275
    return true;
663
664
106
  case ots::kNot:
665
194
  case ots::kAbs:
666
237
  case ots::kNeg:
667
237
    if (stack_size < 1) {
668
1
      return OTS_FAILURE();
669
1
    }
670
236
    argument_stack->pop();
671
236
    argument_stack->push(dummy_result);
672
    // TODO(yusukes): Implement this. We should push a real value for all
673
    // arithmetic and conditional operations.
674
236
    return true;
675
676
421
  case ots::kDiv:
677
    // TODO(yusukes): Should detect div-by-zero errors.
678
421
    if (stack_size < 2) {
679
2
      return OTS_FAILURE();
680
2
    }
681
419
    argument_stack->pop();
682
419
    argument_stack->pop();
683
419
    argument_stack->push(dummy_result);
684
    // TODO(yusukes): Implement this. We should push a real value for all
685
    // arithmetic and conditional operations.
686
419
    return true;
687
688
55
  case ots::kDrop:
689
55
    if (stack_size < 1) {
690
1
      return OTS_FAILURE();
691
1
    }
692
54
    argument_stack->pop();
693
54
    return true;
694
695
1
  case ots::kPut:
696
2
  case ots::kGet:
697
3
  case ots::kIndex:
698
    // For now, just call OTS_FAILURE since there is no way to check whether the
699
    // index argument, |i|, is out-of-bounds or not. Fortunately, no OpenType
700
    // fonts I have (except malicious ones!) use the operators.
701
    // TODO(yusukes): Implement them in a secure way.
702
3
    return OTS_FAILURE();
703
704
1
  case ots::kRoll:
705
    // Likewise, just call OTS_FAILURE for kRoll since there is no way to check
706
    // whether |N| is smaller than the current stack depth or not.
707
    // TODO(yusukes): Implement them in a secure way.
708
1
    return OTS_FAILURE();
709
710
0
  case ots::kRandom:
711
    // For now, we don't handle the 'random' operator since the operator makes
712
    // it hard to analyze hinting code statically.
713
0
    return OTS_FAILURE();
714
715
191
  case ots::kIfElse:
716
191
    if (stack_size < 4) {
717
2
      return OTS_FAILURE();
718
2
    }
719
189
    argument_stack->pop();
720
189
    argument_stack->pop();
721
189
    argument_stack->pop();
722
189
    argument_stack->pop();
723
189
    argument_stack->push(dummy_result);
724
    // TODO(yusukes): Implement this. We should push a real value for all
725
    // arithmetic and conditional operations.
726
189
    return true;
727
728
72
  case ots::kMul:
729
    // TODO(yusukes): Should detect overflows.
730
72
    if (stack_size < 2) {
731
1
      return OTS_FAILURE();
732
1
    }
733
71
    argument_stack->pop();
734
71
    argument_stack->pop();
735
71
    argument_stack->push(dummy_result);
736
    // TODO(yusukes): Implement this. We should push a real value for all
737
    // arithmetic and conditional operations.
738
71
    return true;
739
740
53
  case ots::kSqrt:
741
    // TODO(yusukes): Should check if the argument is negative.
742
53
    if (stack_size < 1) {
743
1
      return OTS_FAILURE();
744
1
    }
745
52
    argument_stack->pop();
746
52
    argument_stack->push(dummy_result);
747
    // TODO(yusukes): Implement this. We should push a real value for all
748
    // arithmetic and conditional operations.
749
52
    return true;
750
751
131
  case ots::kDup:
752
131
    if (stack_size < 1) {
753
1
      return OTS_FAILURE();
754
1
    }
755
130
    argument_stack->pop();
756
130
    argument_stack->push(dummy_result);
757
130
    argument_stack->push(dummy_result);
758
130
    if (ArgumentStackOverflows(argument_stack, cs_ctx.cff2)) {
759
2
      return OTS_FAILURE();
760
2
    }
761
    // TODO(yusukes): Implement this. We should push a real value for all
762
    // arithmetic and conditional operations.
763
128
    return true;
764
765
103
  case ots::kExch:
766
103
    if (stack_size < 2) {
767
1
      return OTS_FAILURE();
768
1
    }
769
102
    argument_stack->pop();
770
102
    argument_stack->pop();
771
102
    argument_stack->push(dummy_result);
772
102
    argument_stack->push(dummy_result);
773
    // TODO(yusukes): Implement this. We should push a real value for all
774
    // arithmetic and conditional operations.
775
102
    return true;
776
777
89
  case ots::kHFlex:
778
89
    if (!(cs_ctx.width_seen)) {
779
2
      return OTS_FAILURE();
780
2
    }
781
87
    if (stack_size != 7) {
782
1
      return OTS_FAILURE();
783
1
    }
784
688
    while (!argument_stack->empty())
785
602
      argument_stack->pop();
786
86
    return true;
787
788
10
  case ots::kFlex:
789
10
    if (!(cs_ctx.width_seen)) {
790
1
      return OTS_FAILURE();
791
1
    }
792
9
    if (stack_size != 13) {
793
1
      return OTS_FAILURE();
794
1
    }
795
112
    while (!argument_stack->empty())
796
104
      argument_stack->pop();
797
8
    return true;
798
799
13
  case ots::kHFlex1:
800
13
    if (!(cs_ctx.width_seen)) {
801
1
      return OTS_FAILURE();
802
1
    }
803
12
    if (stack_size != 9) {
804
1
      return OTS_FAILURE();
805
1
    }
806
110
    while (!argument_stack->empty())
807
99
      argument_stack->pop();
808
11
    return true;
809
810
24
  case ots::kFlex1:
811
24
    if (!(cs_ctx.width_seen)) {
812
1
      return OTS_FAILURE();
813
1
    }
814
23
    if (stack_size != 11) {
815
1
      return OTS_FAILURE();
816
1
    }
817
264
    while (!argument_stack->empty())
818
242
      argument_stack->pop();
819
22
    return true;
820
1.02M
  }
821
822
42
  return OTS_FAILURE_MSG("Undefined operator: %d (0x%x)", op, op);
823
1.02M
}
824
825
// Executes |char_string| and updates |argument_stack|.
826
//
827
// cff: parent OpenTypeCFF reference
828
// call_depth: The current call depth. Initial value is zero.
829
// global_subrs_index: Global subroutines.
830
// local_subrs_index: Local subroutines for the current glyph.
831
// cff_table: A whole CFF table which contains all global and local subroutines.
832
// char_string: A charstring we'll execute. |char_string| can be a main routine
833
//              in CharString INDEX, or a subroutine in GlobalSubr/LocalSubr.
834
// argument_stack: The stack which an operator in |char_string| operates.
835
// cs_ctx: a CharStringContext holding values to persist across subrs, etc.
836
//   endchar_seen: true is set if |char_string| contains 'endchar'.
837
//   width_seen: true is set if |char_string| contains 'width' byte (which
838
//               is 0 or 1 byte) or if cff2
839
//   num_stems: total number of hstems and vstems processed so far.
840
//   cff2: true if this is a CFF2 table
841
//   blend_seen: initially false; set to true if 'blend' operator encountered.
842
//   vsindex_seen: initially false; set to true if 'vsindex' encountered.
843
//   vsindex: initially = PrivateDICT's vsindex; may be changed by 'vsindex'
844
//            operator in CharString
845
bool ExecuteCharString(ots::OpenTypeCFF& cff,
846
                       size_t call_depth,
847
                       const ots::CFFIndex& global_subrs_index,
848
                       const ots::CFFIndex& local_subrs_index,
849
                       ots::Buffer *cff_table,
850
                       ots::Buffer *char_string,
851
                       std::stack<int32_t> *argument_stack,
852
284k
                       ots::CharStringContext& cs_ctx) {
853
284k
  if (call_depth > kMaxSubrNesting) {
854
14
    return OTS_FAILURE();
855
14
  }
856
284k
  cs_ctx.endchar_seen = false;
857
858
284k
  const size_t length = char_string->length();
859
5.62M
  while (char_string->offset() < length) {
860
5.41M
    int32_t operator_or_operand = 0;
861
5.41M
    bool is_operator = false;
862
5.41M
    if (!ReadNextNumberFromCharString(char_string,
863
5.41M
                                           &operator_or_operand,
864
5.41M
                                           &is_operator)) {
865
11
      return OTS_FAILURE();
866
11
    }
867
868
#ifdef DUMP_T2CHARSTRING
869
    /*
870
      You can dump all operators and operands (except mask bytes for hintmask
871
      and cntrmask) by the following code:
872
    */
873
874
      if (!is_operator) {
875
        std::fprintf(stderr, "%d ", operator_or_operand);
876
      } else {
877
        std::fprintf(stderr, "%s\n",
878
           CharStringOperatorToString(
879
               ots::CharStringOperator(operator_or_operand))
880
           );
881
      }
882
#endif
883
884
5.41M
    if (!is_operator) {
885
4.38M
      argument_stack->push(operator_or_operand);
886
4.38M
      if (ArgumentStackOverflows(argument_stack, cs_ctx.cff2)) {
887
14
        return OTS_FAILURE();
888
14
      }
889
4.38M
      continue;
890
4.38M
    }
891
892
    // An operator is found. Execute it.
893
1.02M
    if (!ExecuteCharStringOperator(cff,
894
1.02M
                                   operator_or_operand,
895
1.02M
                                   call_depth,
896
1.02M
                                   global_subrs_index,
897
1.02M
                                   local_subrs_index,
898
1.02M
                                   cff_table,
899
1.02M
                                   char_string,
900
1.02M
                                   argument_stack,
901
1.02M
                                   cs_ctx)) {
902
679
      return OTS_FAILURE();
903
679
    }
904
1.02M
    if (cs_ctx.endchar_seen) {
905
27.7k
      return true;
906
27.7k
    }
907
1.00M
    if (operator_or_operand == ots::kReturn) {
908
43.6k
      return true;
909
43.6k
    }
910
1.00M
  }
911
912
  // No endchar operator is found (CFF1 only)
913
212k
  if (cs_ctx.cff2)
914
212k
    return true;
915
9
  return OTS_FAILURE();
916
212k
}
917
918
// Selects a set of subroutines for |glyph_index| from |cff| and sets it on
919
// |out_local_subrs_to_use|. Returns true on success.
920
bool SelectLocalSubr(const ots::OpenTypeCFF& cff,
921
                     uint16_t glyph_index,  // 0-origin
922
99.0k
                     const ots::CFFIndex **out_local_subrs_to_use) {
923
99.0k
  bool cff2 = (cff.major == 2);
924
99.0k
  *out_local_subrs_to_use = NULL;
925
926
  // First, find local subrs from |local_subrs_per_font|.
927
99.0k
  if ((cff.fd_select.size() > 0) &&
928
392
      (!cff.local_subrs_per_font.empty())) {
929
    // Look up FDArray index for the glyph.
930
356
    const auto& iter = cff.fd_select.find(glyph_index);
931
356
    if (iter == cff.fd_select.end()) {
932
2
      return OTS_FAILURE();
933
2
    }
934
354
    const auto fd_index = iter->second;
935
354
    if (fd_index >= cff.local_subrs_per_font.size()) {
936
1
      return OTS_FAILURE();
937
1
    }
938
353
    *out_local_subrs_to_use = cff.local_subrs_per_font.at(fd_index);
939
98.7k
  } else if (cff.local_subrs) {
940
    // Second, try to use |local_subrs|. Most Latin fonts don't have FDSelect
941
    // entries. If The font has a local subrs index associated with the Top
942
    // DICT (not FDArrays), use it.
943
18.8k
    *out_local_subrs_to_use = cff.local_subrs;
944
79.8k
  } else if (cff2 && cff.local_subrs_per_font.size() == 1) {
945
79.5k
    *out_local_subrs_to_use = cff.local_subrs_per_font.at(0);
946
79.5k
  } else {
947
    // Just return NULL.
948
338
    *out_local_subrs_to_use = NULL;
949
338
  }
950
951
99.0k
  return true;
952
99.0k
}
953
954
}  // namespace
955
956
namespace ots {
957
958
bool ValidateCFFCharStrings(
959
    ots::OpenTypeCFF& cff,
960
    const CFFIndex& global_subrs_index,
961
612
    Buffer* cff_table) {
962
612
  const CFFIndex& char_strings_index = *(cff.charstrings_index);
963
612
  if (char_strings_index.offsets.size() == 0) {
964
3
    return OTS_FAILURE();  // no charstring.
965
3
  }
966
967
  // For each glyph, validate the corresponding charstring.
968
99.3k
  for (unsigned i = 1; i < char_strings_index.offsets.size(); ++i) {
969
    // Prepare a Buffer object, |char_string|, which contains the charstring
970
    // for the |i|-th glyph.
971
99.0k
    const size_t length =
972
99.0k
      char_strings_index.offsets[i] - char_strings_index.offsets[i - 1];
973
99.0k
    if (length > kMaxCharStringLength) {
974
0
      return OTS_FAILURE();
975
0
    }
976
99.0k
    const size_t offset = char_strings_index.offsets[i - 1];
977
99.0k
    cff_table->set_offset(offset);
978
99.0k
    if (!cff_table->Skip(length)) {
979
0
      return OTS_FAILURE();
980
0
    }
981
99.0k
    Buffer char_string(cff_table->buffer() + offset, length);
982
983
    // Get a local subrs for the glyph.
984
99.0k
    const unsigned glyph_index = i - 1;  // index in the map is 0-origin.
985
99.0k
    const CFFIndex *local_subrs_to_use = NULL;
986
99.0k
    if (!SelectLocalSubr(cff,
987
99.0k
                         glyph_index,
988
99.0k
                         &local_subrs_to_use)) {
989
3
      return OTS_FAILURE();
990
3
    }
991
    // If |local_subrs_to_use| is still NULL, use an empty one.
992
99.0k
    CFFIndex default_empty_subrs;
993
99.0k
    if (!local_subrs_to_use){
994
338
      local_subrs_to_use = &default_empty_subrs;
995
338
    }
996
997
    // Check a charstring for the |i|-th glyph.
998
99.0k
    std::stack<int32_t> argument_stack;
999
    // Context to store values that must persist across subrs, etc.
1000
99.0k
    CharStringContext cs_ctx;
1001
99.0k
    cs_ctx.cff2 = (cff.major == 2);
1002
    // CFF2 CharString has no value for width, so we start with true here to
1003
    // error out if width is found.
1004
99.0k
    cs_ctx.width_seen = cs_ctx.cff2;
1005
    // CFF2 CharStrings' default vsindex comes from the associated PrivateDICT
1006
99.0k
    if (cs_ctx.cff2) {
1007
79.6k
      const auto& iter = cff.fd_select.find(glyph_index);
1008
79.6k
      auto fd_index = 0;
1009
79.6k
      if (iter != cff.fd_select.end()) {
1010
160
        fd_index = iter->second;
1011
160
      }
1012
79.6k
      if (fd_index >= (int32_t)cff.vsindex_per_font.size()) {
1013
        // shouldn't get this far with a font in this condition, but just in case
1014
1
        return OTS_FAILURE();  // fd_index out-of-range
1015
1
      }
1016
79.6k
      cs_ctx.vsindex = cff.vsindex_per_font.at(fd_index);
1017
79.6k
    }
1018
1019
#ifdef DUMP_T2CHARSTRING
1020
    fprintf(stderr, "\n---- CharString %*d ----\n", 5, glyph_index);
1021
#endif
1022
1023
99.0k
    if (!ExecuteCharString(cff,
1024
99.0k
                           0 /* initial call_depth is zero */,
1025
99.0k
                           global_subrs_index, *local_subrs_to_use,
1026
99.0k
                           cff_table, &char_string, &argument_stack,
1027
99.0k
                           cs_ctx)) {
1028
315
      return OTS_FAILURE();
1029
315
    }
1030
98.7k
    if (!cs_ctx.cff2 && !cs_ctx.endchar_seen) {
1031
1
      return OTS_FAILURE();
1032
1
    }
1033
98.7k
  }
1034
289
  return true;
1035
609
}
1036
1037
}  // namespace ots
1038
1039
#undef TABLE_NAME