Coverage Report

Created: 2025-10-10 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/hb-cff-interp-dict-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_DICT_COMMON_HH
27
#define HB_CFF_INTERP_DICT_COMMON_HH
28
29
#include "hb-cff-interp-common.hh"
30
31
namespace CFF {
32
33
using namespace OT;
34
35
/* an opstr and the parsed out dict value(s) */
36
struct dict_val_t : op_str_t
37
{
38
268k
  void init () {}
39
0
  void fini () {}
40
};
41
42
typedef dict_val_t num_dict_val_t;
43
44
template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
45
46
template <typename OPSTR=op_str_t>
47
struct top_dict_values_t : dict_values_t<OPSTR>
48
{
49
  void init ()
50
206k
  {
51
206k
    dict_values_t<OPSTR>::init ();
52
206k
    charStringsOffset = 0;
53
206k
    FDArrayOffset = 0;
54
206k
  }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::init()
Line
Count
Source
50
130k
  {
51
130k
    dict_values_t<OPSTR>::init ();
52
130k
    charStringsOffset = 0;
53
130k
    FDArrayOffset = 0;
54
130k
  }
CFF::top_dict_values_t<CFF::op_str_t>::init()
Line
Count
Source
50
75.5k
  {
51
75.5k
    dict_values_t<OPSTR>::init ();
52
75.5k
    charStringsOffset = 0;
53
75.5k
    FDArrayOffset = 0;
54
75.5k
  }
55
354k
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::fini()
Line
Count
Source
55
230k
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::op_str_t>::fini()
Line
Count
Source
55
124k
  void fini () { dict_values_t<OPSTR>::fini (); }
56
57
  int  charStringsOffset;
58
  int  FDArrayOffset;
59
};
60
61
struct dict_opset_t : opset_t<number_t>
62
{
63
  static void process_op (op_code_t op, interp_env_t<number_t>& env)
64
1.67M
  {
65
1.67M
    switch (op) {
66
32.8k
      case OpCode_longintdict:  /* 5-byte integer */
67
32.8k
  env.argStack.push_longint_from_substr (env.str_ref);
68
32.8k
  break;
69
70
9.87k
      case OpCode_BCD:  /* real number */
71
9.87k
  env.argStack.push_real (parse_bcd (env.str_ref));
72
9.87k
  break;
73
74
1.62M
      default:
75
1.62M
  opset_t<number_t>::process_op (op, env);
76
1.62M
  break;
77
1.67M
    }
78
1.67M
  }
79
80
  /* Turns CFF's BCD format into strtod understandable string */
81
  static double parse_bcd (byte_str_ref_t& str_ref)
82
9.87k
  {
83
9.87k
    if (unlikely (str_ref.in_error ())) return .0;
84
85
9.87k
    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
86
87
9.87k
    char buf[32] = {0};
88
9.87k
    unsigned char byte = 0;
89
109k
    for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
90
109k
    {
91
109k
      unsigned nibble;
92
109k
      if (!(i & 1))
93
56.7k
      {
94
56.7k
  if (unlikely (!str_ref.avail ())) break;
95
96
56.7k
  byte = str_ref[0];
97
56.7k
  str_ref.inc ();
98
56.7k
  nibble = byte >> 4;
99
56.7k
      }
100
52.7k
      else
101
52.7k
  nibble = byte & 0x0F;
102
103
109k
      if (unlikely (nibble == RESERVED)) break;
104
109k
      else if (nibble == END)
105
9.71k
      {
106
9.71k
  const char *p = buf;
107
9.71k
  double pv;
108
9.71k
  if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */)))
109
107
    break;
110
9.60k
  return pv;
111
9.71k
      }
112
99.7k
      else
113
99.7k
      {
114
99.7k
  buf[count] = "0123456789.EE?-?"[nibble];
115
99.7k
  if (nibble == EXP_NEG)
116
1.49k
  {
117
1.49k
    ++count;
118
1.49k
    if (unlikely (count == ARRAY_LENGTH (buf))) break;
119
1.48k
    buf[count] = '-';
120
1.48k
  }
121
99.7k
      }
122
109k
    }
123
124
270
    str_ref.set_error ();
125
270
    return .0;
126
9.87k
  }
127
128
  static bool is_hint_op (op_code_t op)
129
18.5k
  {
130
18.5k
    switch (op)
131
18.5k
    {
132
446
      case OpCode_BlueValues:
133
1.13k
      case OpCode_OtherBlues:
134
1.82k
      case OpCode_FamilyBlues:
135
2.12k
      case OpCode_FamilyOtherBlues:
136
2.62k
      case OpCode_StemSnapH:
137
2.79k
      case OpCode_StemSnapV:
138
3.43k
      case OpCode_StdHW:
139
4.10k
      case OpCode_StdVW:
140
4.18k
      case OpCode_BlueScale:
141
4.23k
      case OpCode_BlueShift:
142
4.33k
      case OpCode_BlueFuzz:
143
4.36k
      case OpCode_ForceBold:
144
4.40k
      case OpCode_LanguageGroup:
145
4.44k
      case OpCode_ExpansionFactor:
146
4.44k
  return true;
147
14.1k
      default:
148
14.1k
  return false;
149
18.5k
    }
150
18.5k
  }
151
};
152
153
template <typename VAL=op_str_t>
154
struct top_dict_opset_t : dict_opset_t
155
{
156
  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
157
651k
  {
158
651k
    switch (op) {
159
14.7k
      case OpCode_CharStrings:
160
14.7k
  dictval.charStringsOffset = env.argStack.pop_int ();
161
14.7k
  env.clear_args ();
162
14.7k
  break;
163
7.29k
      case OpCode_FDArray:
164
7.29k
  dictval.FDArrayOffset = env.argStack.pop_int ();
165
7.29k
  env.clear_args ();
166
7.29k
  break;
167
701
      case OpCode_FontMatrix:
168
701
  env.clear_args ();
169
701
  break;
170
628k
      default:
171
628k
  dict_opset_t::process_op (op, env);
172
628k
  break;
173
651k
    }
174
651k
  }
CFF::top_dict_opset_t<CFF::cff1_top_dict_val_t>::process_op(unsigned int, CFF::interp_env_t<CFF::number_t>&, CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>&)
Line
Count
Source
157
305k
  {
158
305k
    switch (op) {
159
9.10k
      case OpCode_CharStrings:
160
9.10k
  dictval.charStringsOffset = env.argStack.pop_int ();
161
9.10k
  env.clear_args ();
162
9.10k
  break;
163
2.20k
      case OpCode_FDArray:
164
2.20k
  dictval.FDArrayOffset = env.argStack.pop_int ();
165
2.20k
  env.clear_args ();
166
2.20k
  break;
167
701
      case OpCode_FontMatrix:
168
701
  env.clear_args ();
169
701
  break;
170
293k
      default:
171
293k
  dict_opset_t::process_op (op, env);
172
293k
  break;
173
305k
    }
174
305k
  }
CFF::top_dict_opset_t<CFF::op_str_t>::process_op(unsigned int, CFF::interp_env_t<CFF::number_t>&, CFF::top_dict_values_t<CFF::op_str_t>&)
Line
Count
Source
157
345k
  {
158
345k
    switch (op) {
159
5.62k
      case OpCode_CharStrings:
160
5.62k
  dictval.charStringsOffset = env.argStack.pop_int ();
161
5.62k
  env.clear_args ();
162
5.62k
  break;
163
5.08k
      case OpCode_FDArray:
164
5.08k
  dictval.FDArrayOffset = env.argStack.pop_int ();
165
5.08k
  env.clear_args ();
166
5.08k
  break;
167
0
      case OpCode_FontMatrix:
168
0
  env.clear_args ();
169
0
  break;
170
334k
      default:
171
334k
  dict_opset_t::process_op (op, env);
172
334k
  break;
173
345k
    }
174
345k
  }
175
};
176
177
template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
178
struct dict_interpreter_t : interpreter_t<ENV>
179
{
180
95.0k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_top_dict_opset_t, CFF::cff2_top_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
180
5.71k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_font_dict_opset_t, CFF::cff2_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
180
10.2k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>, CFF::cff2_priv_dict_interp_env_t>::dict_interpreter_t(CFF::cff2_priv_dict_interp_env_t&)
Line
Count
Source
180
5.56k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_top_dict_opset_t, CFF::cff1_top_dict_values_t, CFF::cff1_top_dict_interp_env_t>::dict_interpreter_t(CFF::cff1_top_dict_interp_env_t&)
Line
Count
Source
180
10.2k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_font_dict_opset_t, CFF::cff1_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
180
26.1k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_t, CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
180
10.6k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_subset_t, CFF::cff1_private_dict_values_base_t<CFF::op_str_t>, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
180
21.8k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_subset_t, CFF::cff2_private_dict_values_base_t<CFF::op_str_t>, CFF::cff2_priv_dict_interp_env_t>::dict_interpreter_t(CFF::cff2_priv_dict_interp_env_t&)
Line
Count
Source
180
4.52k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
Unexecuted instantiation: CFF::dict_interpreter_t<cff2_private_dict_blend_opset_t, cff2_private_blend_encoder_param_t, CFF::cff2_priv_dict_interp_env_t>::dict_interpreter_t(CFF::cff2_priv_dict_interp_env_t&)
181
182
  bool interpret (PARAM& param)
183
95.0k
  {
184
95.0k
    param.init ();
185
2.08M
    while (SUPER::env.str_ref.avail ())
186
1.99M
    {
187
1.99M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
1.99M
      if (unlikely (SUPER::env.in_error ()))
189
1.53k
  return false;
190
1.99M
    }
191
192
93.4k
    return true;
193
95.0k
  }
CFF::dict_interpreter_t<CFF::cff1_top_dict_opset_t, CFF::cff1_top_dict_values_t, CFF::cff1_top_dict_interp_env_t>::interpret(CFF::cff1_top_dict_values_t&)
Line
Count
Source
183
10.2k
  {
184
10.2k
    param.init ();
185
384k
    while (SUPER::env.str_ref.avail ())
186
375k
    {
187
375k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
375k
      if (unlikely (SUPER::env.in_error ()))
189
912
  return false;
190
375k
    }
191
192
9.33k
    return true;
193
10.2k
  }
CFF::dict_interpreter_t<CFF::cff1_font_dict_opset_t, CFF::cff1_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff1_font_dict_values_t&)
Line
Count
Source
183
26.1k
  {
184
26.1k
    param.init ();
185
269k
    while (SUPER::env.str_ref.avail ())
186
243k
    {
187
243k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
243k
      if (unlikely (SUPER::env.in_error ()))
189
130
  return false;
190
243k
    }
191
192
26.0k
    return true;
193
26.1k
  }
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_t, CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>&)
Line
Count
Source
183
10.6k
  {
184
10.6k
    param.init ();
185
218k
    while (SUPER::env.str_ref.avail ())
186
208k
    {
187
208k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
208k
      if (unlikely (SUPER::env.in_error ()))
189
52
  return false;
190
208k
    }
191
192
10.6k
    return true;
193
10.6k
  }
CFF::dict_interpreter_t<CFF::cff2_top_dict_opset_t, CFF::cff2_top_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff2_top_dict_values_t&)
Line
Count
Source
183
5.71k
  {
184
5.71k
    param.init ();
185
354k
    while (SUPER::env.str_ref.avail ())
186
349k
    {
187
349k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
349k
      if (unlikely (SUPER::env.in_error ()))
189
212
  return false;
190
349k
    }
191
192
5.50k
    return true;
193
5.71k
  }
CFF::dict_interpreter_t<CFF::cff2_font_dict_opset_t, CFF::cff2_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff2_font_dict_values_t&)
Line
Count
Source
183
10.2k
  {
184
10.2k
    param.init ();
185
145k
    while (SUPER::env.str_ref.avail ())
186
135k
    {
187
135k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
135k
      if (unlikely (SUPER::env.in_error ()))
189
110
  return false;
190
135k
    }
191
192
10.1k
    return true;
193
10.2k
  }
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>, CFF::cff2_priv_dict_interp_env_t>::interpret(CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>&)
Line
Count
Source
183
5.56k
  {
184
5.56k
    param.init ();
185
64.6k
    while (SUPER::env.str_ref.avail ())
186
59.1k
    {
187
59.1k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
59.1k
      if (unlikely (SUPER::env.in_error ()))
189
41
  return false;
190
59.1k
    }
191
192
5.52k
    return true;
193
5.56k
  }
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_subset_t, CFF::cff1_private_dict_values_base_t<CFF::op_str_t>, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff1_private_dict_values_base_t<CFF::op_str_t>&)
Line
Count
Source
183
21.8k
  {
184
21.8k
    param.init ();
185
499k
    while (SUPER::env.str_ref.avail ())
186
477k
    {
187
477k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
477k
      if (unlikely (SUPER::env.in_error ()))
189
64
  return false;
190
477k
    }
191
192
21.7k
    return true;
193
21.8k
  }
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_subset_t, CFF::cff2_private_dict_values_base_t<CFF::op_str_t>, CFF::cff2_priv_dict_interp_env_t>::interpret(CFF::cff2_private_dict_values_base_t<CFF::op_str_t>&)
Line
Count
Source
183
4.52k
  {
184
4.52k
    param.init ();
185
152k
    while (SUPER::env.str_ref.avail ())
186
148k
    {
187
148k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
188
148k
      if (unlikely (SUPER::env.in_error ()))
189
12
  return false;
190
148k
    }
191
192
4.51k
    return true;
193
4.52k
  }
Unexecuted instantiation: CFF::dict_interpreter_t<cff2_private_dict_blend_opset_t, cff2_private_blend_encoder_param_t, CFF::cff2_priv_dict_interp_env_t>::interpret(cff2_private_blend_encoder_param_t&)
194
195
  private:
196
  typedef interpreter_t<ENV> SUPER;
197
};
198
199
} /* namespace CFF */
200
201
#endif /* HB_CFF_INTERP_DICT_COMMON_HH */