Coverage Report

Created: 2026-06-30 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/hb-cff-interp-common.hh
Line
Count
Source
1
/*
2
 * Copyright © 2018 Adobe Inc.
3
 *
4
 *  This is part of HarfBuzz, a text shaping library.
5
 *
6
 * Permission is hereby granted, without written agreement and without
7
 * license or royalty fees, to use, copy, modify, and distribute this
8
 * software and its documentation for any purpose, provided that the
9
 * above copyright notice and the following two paragraphs appear in
10
 * all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16
 * DAMAGE.
17
 *
18
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
 *
24
 * Adobe Author(s): Michiharu Ariza
25
 */
26
#ifndef HB_CFF_INTERP_COMMON_HH
27
#define HB_CFF_INTERP_COMMON_HH
28
29
extern HB_INTERNAL const unsigned char *endchar_str;
30
31
namespace CFF {
32
33
using namespace OT;
34
35
typedef unsigned int op_code_t;
36
37
38
/* === Dict operators === */
39
40
/* One byte operators (0-31) */
41
0
#define OpCode_version      0 /* CFF Top */
42
0
#define OpCode_Notice     1 /* CFF Top */
43
0
#define OpCode_FullName     2 /* CFF Top */
44
0
#define OpCode_FamilyName   3 /* CFF Top */
45
0
#define OpCode_Weight     4 /* CFF Top */
46
0
#define OpCode_FontBBox     5 /* CFF Top */
47
0
#define OpCode_BlueValues   6 /* CFF Private, CFF2 Private */
48
0
#define OpCode_OtherBlues   7 /* CFF Private, CFF2 Private */
49
0
#define OpCode_FamilyBlues    8 /* CFF Private, CFF2 Private */
50
0
#define OpCode_FamilyOtherBlues   9 /* CFF Private, CFF2 Private */
51
0
#define OpCode_StdHW     10 /* CFF Private, CFF2 Private */
52
0
#define OpCode_StdVW     11 /* CFF Private, CFF2 Private */
53
0
#define OpCode_escape    12 /* All. Shared with CS */
54
0
#define OpCode_UniqueID    13 /* CFF Top */
55
0
#define OpCode_XUID    14 /* CFF Top */
56
0
#define OpCode_charset     15 /* CFF Top (0) */
57
0
#define OpCode_Encoding    16 /* CFF Top (0) */
58
0
#define OpCode_CharStrings   17 /* CFF Top, CFF2 Top */
59
0
#define OpCode_Private     18 /* CFF Top, CFF2 FD */
60
0
#define OpCode_Subrs     19 /* CFF Private, CFF2 Private */
61
0
#define OpCode_defaultWidthX   20 /* CFF Private (0) */
62
0
#define OpCode_nominalWidthX   21 /* CFF Private (0) */
63
0
#define OpCode_vsindexdict   22 /* CFF2 Private/CS */
64
0
#define OpCode_blenddict   23 /* CFF2 Private/CS */
65
0
#define OpCode_vstore    24 /* CFF2 Top */
66
#define OpCode_reserved25  25
67
#define OpCode_reserved26  26
68
#define OpCode_reserved27  27
69
70
/* Numbers */
71
0
#define OpCode_shortint    28 /* 16-bit integer, All */
72
0
#define OpCode_longintdict   29 /* 32-bit integer, All */
73
0
#define OpCode_BCD     30 /* Real number, CFF2 Top/FD */
74
#define OpCode_reserved31  31
75
76
/* 1-byte integers */
77
#define OpCode_OneByteIntFirst   32 /* All. beginning of the range of first byte ints */
78
#define OpCode_OneByteIntLast 246 /* All. ending of the range of first byte int */
79
80
/* 2-byte integers */
81
0
#define OpCode_TwoBytePosInt0 247 /* All. first byte of two byte positive int (+108 to +1131) */
82
0
#define OpCode_TwoBytePosInt1 248
83
0
#define OpCode_TwoBytePosInt2 249
84
0
#define OpCode_TwoBytePosInt3 250
85
86
0
#define OpCode_TwoByteNegInt0 251 /* All. first byte of two byte negative int (-1131 to -108) */
87
0
#define OpCode_TwoByteNegInt1 252
88
0
#define OpCode_TwoByteNegInt2 253
89
0
#define OpCode_TwoByteNegInt3 254
90
91
/* Two byte escape operators 12, (0-41) */
92
0
#define OpCode_ESC_Base   256
93
0
#define Make_OpCode_ESC(byte2)  ((op_code_t)(OpCode_ESC_Base + (byte2)))
94
95
0
inline op_code_t Unmake_OpCode_ESC (op_code_t op)  { return (op_code_t)(op - OpCode_ESC_Base); }
96
0
inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; }
97
0
inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; }
98
99
0
#define OpCode_Copyright  Make_OpCode_ESC(0) /* CFF Top */
100
0
#define OpCode_isFixedPitch Make_OpCode_ESC(1) /* CFF Top (false) */
101
0
#define OpCode_ItalicAngle  Make_OpCode_ESC(2) /* CFF Top (0) */
102
0
#define OpCode_UnderlinePosition Make_OpCode_ESC(3) /* CFF Top (-100) */
103
0
#define OpCode_UnderlineThickness Make_OpCode_ESC(4) /* CFF Top (50) */
104
0
#define OpCode_PaintType  Make_OpCode_ESC(5) /* CFF Top (0) */
105
0
#define OpCode_CharstringType Make_OpCode_ESC(6) /* CFF Top (2) */
106
0
#define OpCode_FontMatrix Make_OpCode_ESC(7) /* CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/
107
0
#define OpCode_StrokeWidth  Make_OpCode_ESC(8) /* CFF Top (0) */
108
0
#define OpCode_BlueScale  Make_OpCode_ESC(9) /* CFF Private, CFF2 Private (0.039625) */
109
0
#define OpCode_BlueShift  Make_OpCode_ESC(10) /* CFF Private, CFF2 Private (7) */
110
0
#define OpCode_BlueFuzz   Make_OpCode_ESC(11) /* CFF Private, CFF2 Private (1) */
111
0
#define OpCode_StemSnapH  Make_OpCode_ESC(12) /* CFF Private, CFF2 Private */
112
0
#define OpCode_StemSnapV  Make_OpCode_ESC(13) /* CFF Private, CFF2 Private */
113
0
#define OpCode_ForceBold  Make_OpCode_ESC(14) /* CFF Private (false) */
114
#define OpCode_reservedESC15  Make_OpCode_ESC(15)
115
#define OpCode_reservedESC16  Make_OpCode_ESC(16)
116
0
#define OpCode_LanguageGroup  Make_OpCode_ESC(17) /* CFF Private, CFF2 Private (0) */
117
0
#define OpCode_ExpansionFactor  Make_OpCode_ESC(18) /* CFF Private, CFF2 Private (0.06) */
118
0
#define OpCode_initialRandomSeed Make_OpCode_ESC(19) /* CFF Private (0) */
119
0
#define OpCode_SyntheticBase  Make_OpCode_ESC(20) /* CFF Top */
120
0
#define OpCode_PostScript Make_OpCode_ESC(21) /* CFF Top */
121
0
#define OpCode_BaseFontName Make_OpCode_ESC(22) /* CFF Top */
122
0
#define OpCode_BaseFontBlend  Make_OpCode_ESC(23) /* CFF Top */
123
#define OpCode_reservedESC24  Make_OpCode_ESC(24)
124
#define OpCode_reservedESC25  Make_OpCode_ESC(25)
125
#define OpCode_reservedESC26  Make_OpCode_ESC(26)
126
#define OpCode_reservedESC27  Make_OpCode_ESC(27)
127
#define OpCode_reservedESC28  Make_OpCode_ESC(28)
128
#define OpCode_reservedESC29  Make_OpCode_ESC(29)
129
0
#define OpCode_ROS    Make_OpCode_ESC(30) /* CFF Top_CID */
130
0
#define OpCode_CIDFontVersion Make_OpCode_ESC(31) /* CFF Top_CID (0) */
131
0
#define OpCode_CIDFontRevision  Make_OpCode_ESC(32) /* CFF Top_CID (0) */
132
0
#define OpCode_CIDFontType  Make_OpCode_ESC(33) /* CFF Top_CID (0) */
133
0
#define OpCode_CIDCount   Make_OpCode_ESC(34) /* CFF Top_CID (8720) */
134
0
#define OpCode_UIDBase    Make_OpCode_ESC(35) /* CFF Top_CID */
135
0
#define OpCode_FDArray    Make_OpCode_ESC(36) /* CFF Top_CID, CFF2 Top */
136
0
#define OpCode_FDSelect   Make_OpCode_ESC(37) /* CFF Top_CID, CFF2 Top */
137
0
#define OpCode_FontName   Make_OpCode_ESC(38) /* CFF Top_CID */
138
139
140
/* === CharString operators === */
141
142
0
#define OpCode_hstem      1 /* CFF, CFF2 */
143
#define OpCode_Reserved2    2
144
0
#define OpCode_vstem      3 /* CFF, CFF2 */
145
0
#define OpCode_vmoveto      4 /* CFF, CFF2 */
146
0
#define OpCode_rlineto      5 /* CFF, CFF2 */
147
0
#define OpCode_hlineto      6 /* CFF, CFF2 */
148
0
#define OpCode_vlineto      7 /* CFF, CFF2 */
149
0
#define OpCode_rrcurveto    8 /* CFF, CFF2 */
150
#define OpCode_Reserved9    9
151
0
#define OpCode_callsubr    10 /* CFF, CFF2 */
152
0
#define OpCode_return    11 /* CFF */
153
//#define OpCode_escape    12 /* CFF, CFF2 */
154
#define OpCode_Reserved13  13
155
0
#define OpCode_endchar     14 /* CFF */
156
0
#define OpCode_vsindexcs   15 /* CFF2 */
157
0
#define OpCode_blendcs     16 /* CFF2 */
158
#define OpCode_Reserved17  17
159
0
#define OpCode_hstemhm     18 /* CFF, CFF2 */
160
0
#define OpCode_hintmask    19 /* CFF, CFF2 */
161
0
#define OpCode_cntrmask    20 /* CFF, CFF2 */
162
0
#define OpCode_rmoveto     21 /* CFF, CFF2 */
163
0
#define OpCode_hmoveto     22 /* CFF, CFF2 */
164
0
#define OpCode_vstemhm     23 /* CFF, CFF2 */
165
0
#define OpCode_rcurveline  24 /* CFF, CFF2 */
166
0
#define OpCode_rlinecurve  25 /* CFF, CFF2 */
167
0
#define OpCode_vvcurveto   26 /* CFF, CFF2 */
168
0
#define OpCode_hhcurveto   27 /* CFF, CFF2 */
169
//#define OpCode_shortint  28 /* CFF, CFF2 */
170
0
#define OpCode_callgsubr   29 /* CFF, CFF2 */
171
0
#define OpCode_vhcurveto   30 /* CFF, CFF2 */
172
0
#define OpCode_hvcurveto   31 /* CFF, CFF2 */
173
174
0
#define OpCode_fixedcs    255 /* 32-bit fixed */
175
176
/* Two byte escape operators 12, (0-41) */
177
0
#define OpCode_dotsection Make_OpCode_ESC(0) /* CFF (obsoleted) */
178
#define OpCode_ReservedESC1 Make_OpCode_ESC(1)
179
#define OpCode_ReservedESC2 Make_OpCode_ESC(2)
180
#define OpCode_and    Make_OpCode_ESC(3) /* CFF */
181
#define OpCode_or   Make_OpCode_ESC(4) /* CFF */
182
#define OpCode_not    Make_OpCode_ESC(5) /* CFF */
183
#define OpCode_ReservedESC6 Make_OpCode_ESC(6)
184
#define OpCode_ReservedESC7 Make_OpCode_ESC(7)
185
#define OpCode_ReservedESC8 Make_OpCode_ESC(8)
186
#define OpCode_abs    Make_OpCode_ESC(9) /* CFF */
187
#define OpCode_add    Make_OpCode_ESC(10) /* CFF */
188
#define OpCode_sub    Make_OpCode_ESC(11) /* CFF */
189
#define OpCode_div    Make_OpCode_ESC(12) /* CFF */
190
#define OpCode_ReservedESC13  Make_OpCode_ESC(13)
191
#define OpCode_neg    Make_OpCode_ESC(14) /* CFF */
192
#define OpCode_eq   Make_OpCode_ESC(15) /* CFF */
193
#define OpCode_ReservedESC16  Make_OpCode_ESC(16)
194
#define OpCode_ReservedESC17  Make_OpCode_ESC(17)
195
#define OpCode_drop   Make_OpCode_ESC(18) /* CFF */
196
#define OpCode_ReservedESC19  Make_OpCode_ESC(19)
197
#define OpCode_put    Make_OpCode_ESC(20) /* CFF */
198
#define OpCode_get    Make_OpCode_ESC(21) /* CFF */
199
#define OpCode_ifelse   Make_OpCode_ESC(22) /* CFF */
200
#define OpCode_random   Make_OpCode_ESC(23) /* CFF */
201
#define OpCode_mul    Make_OpCode_ESC(24) /* CFF */
202
//#define OpCode_reservedESC25  Make_OpCode_ESC(25)
203
#define OpCode_sqrt   Make_OpCode_ESC(26) /* CFF */
204
#define OpCode_dup    Make_OpCode_ESC(27) /* CFF */
205
#define OpCode_exch   Make_OpCode_ESC(28) /* CFF */
206
#define OpCode_index    Make_OpCode_ESC(29) /* CFF */
207
#define OpCode_roll   Make_OpCode_ESC(30) /* CFF */
208
#define OpCode_reservedESC31  Make_OpCode_ESC(31)
209
#define OpCode_reservedESC32  Make_OpCode_ESC(32)
210
#define OpCode_reservedESC33  Make_OpCode_ESC(33)
211
0
#define OpCode_hflex    Make_OpCode_ESC(34) /* CFF, CFF2 */
212
0
#define OpCode_flex   Make_OpCode_ESC(35) /* CFF, CFF2 */
213
0
#define OpCode_hflex1   Make_OpCode_ESC(36) /* CFF, CFF2 */
214
0
#define OpCode_flex1    Make_OpCode_ESC(37) /* CFF, CFF2 */
215
216
217
0
#define OpCode_Invalid    0xFFFFu
218
219
220
struct number_t
221
{
222
0
  void set_int (int v)       { value = v; }
223
  bool to_int (int *v) const
224
0
  {
225
0
    if (unlikely (!(value >= INT_MIN && value <= INT_MAX)))
226
0
    {
227
0
      *v = 0;
228
0
      return false;
229
0
    }
230
0
    *v = (int) value;
231
0
    return true;
232
0
  }
233
  int to_int () const
234
0
  {
235
0
    int v;
236
0
    if (likely (to_int (&v))) return v;
237
0
    return value < 0 ? INT_MIN : value > 0 ? INT_MAX : 0;
238
0
  }
239
240
0
  void set_fixed (int32_t v) { value = v / 65536.0; }
241
0
  int32_t to_fixed () const  { return value * 65536.0; }
242
243
0
  void set_real (double v)   { value = v; }
244
0
  double to_real () const    { return value; }
245
246
  bool in_int_range () const
247
0
  { return value >= INT16_MIN && value <= INT16_MAX && (double) (int16_t) value == value; }
248
249
0
  bool operator >  (const number_t &n) const { return value > n.to_real (); }
250
0
  bool operator <  (const number_t &n) const { return n > *this; }
251
0
  bool operator >= (const number_t &n) const { return !(*this < n); }
252
0
  bool operator <= (const number_t &n) const { return !(*this > n); }
253
254
  const number_t &operator += (const number_t &n)
255
0
  {
256
0
    set_real (to_real () + n.to_real ());
257
258
0
    return *this;
259
0
  }
260
261
  protected:
262
  double value = 0.;
263
};
264
265
/* byte string */
266
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
267
{
268
  hb_ubytes_t as_ubytes (unsigned l) const
269
0
  { return hb_ubytes_t ((const unsigned char *) this, l); }
270
271
  // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
272
  template <typename T, typename V>
273
  static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
274
0
  {
275
0
    TRACE_SERIALIZE (this);
276
0
277
0
    HBUINT8 *p = c->allocate_size<HBUINT8> (1);
278
0
    if (unlikely (!p)) return_trace (false);
279
0
    *p = intOp;
280
0
281
0
    T *ip = c->allocate_size<T> (T::static_size);
282
0
    if (unlikely (!ip)) return_trace (false);
283
0
    return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW));
284
0
  }
Unexecuted instantiation: bool CFF::UnsizedByteStr::serialize_int<OT::NumType<true, int, 4u>, int>(hb_serialize_context_t*, unsigned int, int)
Unexecuted instantiation: bool CFF::UnsizedByteStr::serialize_int<OT::NumType<true, short, 2u>, int>(hb_serialize_context_t*, unsigned int, int)
Unexecuted instantiation: bool CFF::UnsizedByteStr::serialize_int<OT::NumType<true, short, 2u>, unsigned int>(hb_serialize_context_t*, unsigned int, unsigned int)
285
286
  template <typename V>
287
  static bool serialize_int4 (hb_serialize_context_t *c, V value)
288
  { return serialize_int<HBINT32> (c, OpCode_longintdict, value); }
289
290
  template <typename V>
291
  static bool serialize_int2 (hb_serialize_context_t *c, V value)
292
0
  { return serialize_int<HBINT16> (c, OpCode_shortint, value); }
293
294
  /* Defining null_size allows a Null object may be created. Should be safe because:
295
   * A descendent struct Dict uses a Null pointer to indicate a missing table,
296
   * checked before access.
297
   */
298
  DEFINE_SIZE_MIN(0);
299
};
300
301
/* A byte string associated with the current offset and an error condition */
302
struct byte_str_ref_t
303
{
304
  byte_str_ref_t ()
305
0
    : str () {}
306
307
  byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
308
0
    : str (str_) { set_offset (offset_); }
309
310
  void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
311
0
  {
312
0
    str = str_;
313
0
    set_offset (offset_);
314
0
  }
315
316
0
  const unsigned char& operator [] (int i) {
317
0
    if (unlikely ((unsigned int) (get_offset () + i) >= str.length))
318
0
    {
319
0
      set_error ();
320
0
      return Null (unsigned char);
321
0
    }
322
0
    return str.arrayZ[get_offset () + i];
323
0
  }
324
325
0
  unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; }
326
327
  /* Conversion to hb_ubytes_t */
328
0
  operator hb_ubytes_t () const { return str.sub_array (get_offset ()); }
329
330
  hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
331
0
  { return str.sub_array (offset_, len_); }
332
333
  bool avail (unsigned int count=1) const
334
0
  { return get_offset () + count <= str.length; }
335
  void inc (unsigned int count=1)
336
0
  {
337
    /* Automatically puts us in error if count is out-of-range. */
338
0
    set_offset (get_offset () + count);
339
0
  }
340
341
  /* We (ab)use ubytes backwards_length as a cursor (called offset),
342
   * as well as to store error condition. */
343
344
0
  unsigned get_offset () const { return str.backwards_length; }
345
0
  void set_offset (unsigned offset) { str.backwards_length = offset; }
346
347
0
  void set_error ()      { str.backwards_length = str.length + 1; }
348
0
  bool in_error () const { return str.backwards_length > str.length; }
349
350
0
  unsigned total_size () const { return str.length; }
351
352
  protected:
353
  hb_ubytes_t       str;
354
};
355
356
/* stack */
357
template <typename ELEM, int LIMIT>
358
struct cff_stack_t
359
{
360
  ELEM& operator [] (unsigned int i)
361
0
  {
362
0
    if (unlikely (i >= length))
363
0
    {
364
0
      set_error ();
365
0
      return Crap (ELEM);
366
0
    }
367
0
    return arrayZ[i];
368
0
  }
369
370
  void push (const ELEM &v)
371
0
  {
372
0
    if (likely (length < LIMIT))
373
0
      arrayZ[length++] = v;
374
0
    else
375
0
      set_error ();
376
0
  }
377
  ELEM &push ()
378
0
  {
379
0
    if (likely (length < LIMIT))
380
0
      return arrayZ[length++];
381
0
    else
382
0
    {
383
0
      set_error ();
384
0
      return Crap (ELEM);
385
0
    }
386
0
  }
387
388
  ELEM& pop ()
389
0
  {
390
0
    if (likely (length > 0))
391
0
      return arrayZ[--length];
392
0
    else
393
0
    {
394
0
      set_error ();
395
0
      return Crap (ELEM);
396
0
    }
397
0
  }
Unexecuted instantiation: CFF::cff_stack_t<CFF::number_t, 513>::pop()
Unexecuted instantiation: CFF::cff_stack_t<CFF::call_context_t, 10>::pop()
398
  void pop (unsigned int n)
399
0
  {
400
0
    if (likely (length >= n))
401
0
      length -= n;
402
0
    else
403
0
      set_error ();
404
0
  }
405
406
  const ELEM& peek ()
407
  {
408
    if (unlikely (length == 0))
409
    {
410
      set_error ();
411
      return Null (ELEM);
412
    }
413
    return arrayZ[length - 1];
414
  }
415
416
  void unpop ()
417
  {
418
    if (likely (length < LIMIT))
419
      length++;
420
    else
421
      set_error ();
422
  }
423
424
  void clear () { length = 0; }
425
426
0
  bool in_error () const { return (error); }
Unexecuted instantiation: CFF::cff_stack_t<CFF::number_t, 513>::in_error() const
Unexecuted instantiation: CFF::cff_stack_t<CFF::call_context_t, 10>::in_error() const
427
0
  void set_error ()      { error = true; }
Unexecuted instantiation: CFF::cff_stack_t<CFF::number_t, 513>::set_error()
Unexecuted instantiation: CFF::cff_stack_t<CFF::call_context_t, 10>::set_error()
428
429
0
  unsigned int get_count () const { return length; }
Unexecuted instantiation: CFF::cff_stack_t<CFF::number_t, 513>::get_count() const
Unexecuted instantiation: CFF::cff_stack_t<CFF::call_context_t, 10>::get_count() const
430
0
  bool is_empty () const          { return !length; }
Unexecuted instantiation: CFF::cff_stack_t<CFF::number_t, 513>::is_empty() const
Unexecuted instantiation: CFF::cff_stack_t<CFF::call_context_t, 10>::is_empty() const
431
432
  hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const
433
0
  { return hb_array_t<const ELEM> (arrayZ).sub_array (start, length); }
434
435
  bool error = false;
436
  unsigned int length = 0;
437
  ELEM arrayZ[LIMIT];
438
};
439
440
/* argument stack */
441
template <typename ARG=number_t>
442
struct arg_stack_t : cff_stack_t<ARG, 513>
443
{
444
  void push_int (int v)
445
0
  {
446
0
    ARG &n = S::push ();
447
0
    n.set_int (v);
448
0
  }
449
450
  void push_fixed (int32_t v)
451
0
  {
452
0
    ARG &n = S::push ();
453
0
    n.set_fixed (v);
454
0
  }
455
456
  void push_real (double v)
457
0
  {
458
0
    ARG &n = S::push ();
459
0
    n.set_real (v);
460
0
  }
461
462
  ARG& pop_num () { return this->pop (); }
463
464
  int pop_int ()
465
0
  {
466
0
    int v;
467
0
    if (unlikely (!this->pop ().to_int (&v)))
468
0
      S::set_error ();
469
0
    return v;
470
0
  }
471
472
  unsigned int pop_uint ()
473
0
  {
474
0
    int i = pop_int ();
475
0
    if (unlikely (i < 0))
476
0
    {
477
0
      i = 0;
478
0
      S::set_error ();
479
0
    }
480
0
    return (unsigned) i;
481
0
  }
482
483
  void push_longint_from_substr (byte_str_ref_t& str_ref)
484
0
  {
485
0
    push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3]));
486
0
    str_ref.inc (4);
487
0
  }
488
489
  bool push_fixed_from_substr (byte_str_ref_t& str_ref)
490
0
  {
491
0
    if (unlikely (!str_ref.avail (4)))
492
0
      return false;
493
0
    push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]);
494
0
    str_ref.inc (4);
495
0
    return true;
496
0
  }
497
498
  private:
499
  typedef cff_stack_t<ARG, 513> S;
500
};
501
502
/* an operator prefixed by its operands in a byte string */
503
struct op_str_t
504
{
505
  /* This used to have a hb_ubytes_t. Using a pointer and length
506
   * in a particular order, saves 8 bytes in this struct and more
507
   * in our parsed_cs_op_t subclass. */
508
509
  const unsigned char *ptr = nullptr;
510
511
  op_code_t  op = OpCode_Invalid;
512
513
  uint8_t length = 0;
514
};
515
516
/* base of OP_SERIALIZER */
517
struct op_serializer_t
518
{
519
  protected:
520
  bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const
521
0
  {
522
0
    TRACE_SERIALIZE (this);
523
0
524
0
    unsigned char *d = c->allocate_size<unsigned char> (opstr.length);
525
0
    if (unlikely (!d)) return_trace (false);
526
0
    /* Faster than hb_memcpy for small strings. */
527
0
    for (unsigned i = 0; i < opstr.length; i++)
528
0
      d[i] = opstr.ptr[i];
529
0
    return_trace (true);
530
0
  }
531
};
532
533
template <typename VAL>
534
struct parsed_values_t
535
{
536
  void init ()
537
0
  {
538
0
    opStart = 0;
539
0
    values.init ();
540
0
  }
Unexecuted instantiation: CFF::parsed_values_t<CFF::parsed_cs_op_t>::init()
Unexecuted instantiation: CFF::parsed_values_t<CFF::cff1_top_dict_val_t>::init()
Unexecuted instantiation: CFF::parsed_values_t<CFF::op_str_t>::init()
Unexecuted instantiation: CFF::parsed_values_t<CFF::dict_val_t>::init()
541
0
  void fini () { values.fini (); }
Unexecuted instantiation: CFF::parsed_values_t<CFF::cff1_top_dict_val_t>::fini()
Unexecuted instantiation: CFF::parsed_values_t<CFF::op_str_t>::fini()
542
543
  void alloc (unsigned n)
544
  {
545
    values.alloc_exact (n);
546
  }
547
548
  void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ())
549
0
  {
550
0
    VAL *val = values.push (v);
551
0
    val->op = op;
552
0
    auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
553
0
    val->ptr = arr.arrayZ;
554
0
    val->length = arr.length;
555
0
    opStart = str_ref.get_offset ();
556
0
  }
Unexecuted instantiation: CFF::parsed_values_t<CFF::parsed_cs_op_t>::add_op(unsigned int, CFF::byte_str_ref_t const&, CFF::parsed_cs_op_t const&)
Unexecuted instantiation: CFF::parsed_values_t<CFF::cff1_top_dict_val_t>::add_op(unsigned int, CFF::byte_str_ref_t const&, CFF::cff1_top_dict_val_t const&)
Unexecuted instantiation: CFF::parsed_values_t<CFF::op_str_t>::add_op(unsigned int, CFF::byte_str_ref_t const&, CFF::op_str_t const&)
Unexecuted instantiation: CFF::parsed_values_t<CFF::dict_val_t>::add_op(unsigned int, CFF::byte_str_ref_t const&, CFF::dict_val_t const&)
557
558
  bool has_op (op_code_t op) const
559
  {
560
    for (const auto& v : values)
561
      if (v.op == op) return true;
562
    return false;
563
  }
564
565
0
  unsigned get_count () const { return values.length; }
566
0
  const VAL &operator [] (unsigned int i) const { return values[i]; }
567
568
  unsigned int       opStart;
569
  hb_vector_t<VAL>   values;
570
};
571
572
template <typename ARG=number_t>
573
struct interp_env_t
574
{
575
  interp_env_t () {}
576
  interp_env_t (const hb_ubytes_t &str_)
577
0
  {
578
0
    str_ref.reset (str_);
579
0
  }
580
  bool in_error () const
581
0
  { return str_ref.in_error () || argStack.in_error (); }
582
583
0
  void set_error () { str_ref.set_error (); }
584
585
  op_code_t fetch_op ()
586
0
  {
587
0
    op_code_t  op = OpCode_Invalid;
588
0
    if (unlikely (!str_ref.avail ()))
589
0
      return OpCode_Invalid;
590
0
    op = (op_code_t) str_ref.head_unchecked ();
591
0
    str_ref.inc ();
592
0
    if (op == OpCode_escape) {
593
0
      if (unlikely (!str_ref.avail ()))
594
0
  return OpCode_Invalid;
595
0
      op = Make_OpCode_ESC (str_ref.head_unchecked ());
596
0
      str_ref.inc ();
597
0
    }
598
0
    return op;
599
0
  }
600
601
0
  const ARG& eval_arg (unsigned int i) { return argStack[i]; }
602
603
0
  ARG& pop_arg () { return argStack.pop (); }
604
0
  void pop_n_args (unsigned int n) { argStack.pop (n); }
605
606
0
  void clear_args () { pop_n_args (argStack.get_count ()); }
607
608
  byte_str_ref_t
609
    str_ref;
610
  arg_stack_t<ARG>
611
    argStack;
612
};
613
614
using num_interp_env_t =  interp_env_t<>;
615
616
template <typename ARG=number_t>
617
struct opset_t
618
{
619
  static void process_op (op_code_t op, interp_env_t<ARG>& env)
620
0
  {
621
0
    switch (op) {
622
0
      case OpCode_shortint:
623
0
  env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1]));
624
0
  env.str_ref.inc (2);
625
0
  break;
626
627
0
      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
628
0
      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
629
0
  env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
630
0
  env.str_ref.inc ();
631
0
  break;
632
633
0
      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
634
0
      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
635
0
  env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
636
0
  env.str_ref.inc ();
637
0
  break;
638
639
0
      default:
640
  /* 1-byte integer */
641
0
  if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
642
0
  {
643
0
    env.argStack.push_int ((int)op - 139);
644
0
  } else {
645
    /* invalid unknown operator */
646
0
    env.clear_args ();
647
0
  }
648
0
  break;
649
0
    }
650
0
  }
651
};
652
653
template <typename ENV>
654
struct interpreter_t
655
{
656
0
  interpreter_t (ENV& env_) : env (env_) {}
Unexecuted instantiation: CFF::interpreter_t<CFF::interp_env_t<CFF::number_t> >::interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Unexecuted instantiation: CFF::interpreter_t<CFF::cff2_priv_dict_interp_env_t>::interpreter_t(CFF::cff2_priv_dict_interp_env_t&)
Unexecuted instantiation: CFF::interpreter_t<CFF::cff1_top_dict_interp_env_t>::interpreter_t(CFF::cff1_top_dict_interp_env_t&)
Unexecuted instantiation: CFF::interpreter_t<CFF::cff1_cs_interp_env_t>::interpreter_t(CFF::cff1_cs_interp_env_t&)
Unexecuted instantiation: CFF::interpreter_t<CFF::cff2_cs_interp_env_t<CFF::number_t> >::interpreter_t(CFF::cff2_cs_interp_env_t<CFF::number_t>&)
657
  ENV& env;
658
};
659
660
} /* namespace CFF */
661
662
#endif /* HB_CFF_INTERP_COMMON_HH */