Coverage Report

Created: 2026-05-16 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/test/fuzzing/hb-shape-input.hh
Line
Count
Source
1
#include "hb-fuzzer.hh"
2
3
#include <hb-ot.h>
4
#include <string.h>
5
6
#include <algorithm>
7
#include <cmath>
8
#include <stdlib.h>
9
#include <vector>
10
11
enum _fuzzing_shape_input_status_t
12
{
13
  HB_FUZZING_SHAPE_INPUT_RAW = 0,
14
  HB_FUZZING_SHAPE_INPUT_EXTENDED = 1,
15
  HB_FUZZING_SHAPE_INPUT_MALFORMED = 2,
16
};
17
18
struct _fuzzing_shape_input_t
19
{
20
  hb_blob_t *blob = nullptr;
21
  hb_face_t *face = nullptr;
22
  hb_font_t *font = nullptr;
23
  std::vector<hb_codepoint_t> text;
24
  std::vector<hb_variation_t> variations;
25
26
  ~_fuzzing_shape_input_t ()
27
81.9k
  {
28
81.9k
    hb_font_destroy (font);
29
81.9k
    hb_face_destroy (face);
30
81.9k
    hb_blob_destroy (blob);
31
81.9k
  }
32
};
33
34
static bool
35
_fuzzing_apply_extended_shape_ops (hb_face_t *face,
36
                                   std::vector<hb_codepoint_t> *text,
37
                                   std::vector<hb_variation_t> *variations,
38
                                   const uint8_t *ops,
39
                                   size_t ops_len)
40
1.35k
{
41
1.35k
  variations->clear ();
42
1.35k
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
1.35k
  std::vector<hb_ot_var_axis_info_t> axes;
44
1.35k
  if (axis_count)
45
344
  {
46
344
    axes.resize (axis_count);
47
344
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
344
  }
49
50
1.35k
  const uint8_t *p = ops;
51
1.35k
  const uint8_t *end = ops + ops_len;
52
24.0k
  while (p < end)
53
23.3k
  {
54
23.3k
    uint8_t op;
55
23.3k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
23.3k
    switch (op)
59
23.3k
    {
60
661
      case HB_FUZZING_OP_TEXT_ADD:
61
818
      case HB_FUZZING_OP_TEXT_DEL:
62
818
      {
63
818
        uint32_t count;
64
818
        if (!_fuzzing_read_u32_value (p, end, &count))
65
12
          return false;
66
67
26.5k
        for (uint32_t i = 0; i < count; i++)
68
25.9k
        {
69
25.9k
          uint32_t cp;
70
25.9k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
168
            return false;
72
25.7k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
18.4k
            text->push_back (cp);
74
7.38k
          else
75
7.38k
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
25.7k
        }
77
638
        break;
78
806
      }
79
80
14.7k
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
14.7k
        variations->clear ();
82
14.7k
        break;
83
84
511
      case HB_FUZZING_OP_AXIS_SET:
85
511
      {
86
511
        uint32_t count;
87
511
        if (!_fuzzing_read_u32_value (p, end, &count))
88
5
          return false;
89
90
11.5k
        for (uint32_t i = 0; i < count; i++)
91
11.2k
        {
92
11.2k
          uint32_t tag;
93
11.2k
          uint8_t mode;
94
11.2k
          float minimum, middle, maximum;
95
11.2k
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
11.1k
              !_fuzzing_read_value (p, end, &mode) ||
97
11.1k
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
11.1k
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
11.1k
              !_fuzzing_read_f32_value (p, end, &maximum))
100
130
            return false;
101
102
11.0k
          if (!axis_count)
103
3.28k
            continue;
104
105
1.12M
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
1.12M
          {
107
1.12M
            if (axes[axis_index].tag != tag)
108
1.12M
              continue;
109
110
1.92k
            float value = axes[axis_index].default_value;
111
1.92k
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
924
              value = axes[axis_index].default_value;
113
998
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
957
            {
115
957
              if (!std::isnan (middle))
116
934
                value = middle;
117
23
              else if (!std::isnan (minimum))
118
12
                value = minimum;
119
11
              else if (!std::isnan (maximum))
120
8
                value = maximum;
121
957
            }
122
41
            else
123
41
              return false;
124
125
1.88k
            bool updated = false;
126
1.88k
            for (auto &variation : *variations)
127
3.03k
              if (variation.tag == tag)
128
1.49k
              {
129
1.49k
                variation.value = value;
130
1.49k
                updated = true;
131
1.49k
                break;
132
1.49k
              }
133
1.88k
            if (!updated)
134
382
              variations->push_back ({tag, value});
135
1.88k
            break;
136
1.92k
          }
137
7.79k
        }
138
335
        break;
139
506
      }
140
141
1.38k
      case HB_FUZZING_OP_SET_FLAGS:
142
1.38k
      {
143
1.38k
        uint32_t ignored;
144
1.38k
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
13
          return false;
146
1.37k
        break;
147
1.38k
      }
148
149
3.50k
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
3.50k
        break;
151
152
1.14k
      case HB_FUZZING_OP_SET_CLEAR:
153
2.09k
      case HB_FUZZING_OP_SET_INVERT:
154
2.09k
      {
155
2.09k
        uint8_t ignored;
156
2.09k
        if (!_fuzzing_read_value (p, end, &ignored))
157
6
          return false;
158
2.08k
        break;
159
2.09k
      }
160
161
2.08k
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
169
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
169
      {
164
169
        uint8_t ignored_set_type;
165
169
        uint32_t count;
166
169
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
164
            !_fuzzing_read_u32_value (p, end, &count))
168
14
          return false;
169
9.71k
        for (uint32_t i = 0; i < count; i++)
170
9.64k
        {
171
9.64k
          uint32_t ignored_start, ignored_end;
172
9.64k
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
9.59k
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
90
            return false;
175
9.64k
        }
176
65
        break;
177
155
      }
178
179
146
      default:
180
146
        return false;
181
23.3k
    }
182
23.3k
  }
183
184
726
  return true;
185
1.35k
}
hb-shape-fuzzer.cc:_fuzzing_apply_extended_shape_ops(hb_face_t*, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*, std::__1::vector<hb_variation_t, std::__1::allocator<hb_variation_t> >*, unsigned char const*, unsigned long)
Line
Count
Source
40
305
{
41
305
  variations->clear ();
42
305
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
305
  std::vector<hb_ot_var_axis_info_t> axes;
44
305
  if (axis_count)
45
126
  {
46
126
    axes.resize (axis_count);
47
126
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
126
  }
49
50
305
  const uint8_t *p = ops;
51
305
  const uint8_t *end = ops + ops_len;
52
15.8k
  while (p < end)
53
15.7k
  {
54
15.7k
    uint8_t op;
55
15.7k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
15.7k
    switch (op)
59
15.7k
    {
60
67
      case HB_FUZZING_OP_TEXT_ADD:
61
111
      case HB_FUZZING_OP_TEXT_DEL:
62
111
      {
63
111
        uint32_t count;
64
111
        if (!_fuzzing_read_u32_value (p, end, &count))
65
3
          return false;
66
67
3.93k
        for (uint32_t i = 0; i < count; i++)
68
3.86k
        {
69
3.86k
          uint32_t cp;
70
3.86k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
42
            return false;
72
3.82k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
1.47k
            text->push_back (cp);
74
2.34k
          else
75
2.34k
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
3.82k
        }
77
66
        break;
78
108
      }
79
80
13.9k
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
13.9k
        variations->clear ();
82
13.9k
        break;
83
84
156
      case HB_FUZZING_OP_AXIS_SET:
85
156
      {
86
156
        uint32_t count;
87
156
        if (!_fuzzing_read_u32_value (p, end, &count))
88
1
          return false;
89
90
2.58k
        for (uint32_t i = 0; i < count; i++)
91
2.47k
        {
92
2.47k
          uint32_t tag;
93
2.47k
          uint8_t mode;
94
2.47k
          float minimum, middle, maximum;
95
2.47k
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
2.46k
              !_fuzzing_read_value (p, end, &mode) ||
97
2.46k
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
2.45k
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
2.45k
              !_fuzzing_read_f32_value (p, end, &maximum))
100
30
            return false;
101
102
2.44k
          if (!axis_count)
103
437
            continue;
104
105
42.9k
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
41.7k
          {
107
41.7k
            if (axes[axis_index].tag != tag)
108
40.8k
              continue;
109
110
806
            float value = axes[axis_index].default_value;
111
806
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
453
              value = axes[axis_index].default_value;
113
353
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
336
            {
115
336
              if (!std::isnan (middle))
116
314
                value = middle;
117
22
              else if (!std::isnan (minimum))
118
11
                value = minimum;
119
11
              else if (!std::isnan (maximum))
120
8
                value = maximum;
121
336
            }
122
17
            else
123
17
              return false;
124
125
789
            bool updated = false;
126
789
            for (auto &variation : *variations)
127
1.01k
              if (variation.tag == tag)
128
651
              {
129
651
                variation.value = value;
130
651
                updated = true;
131
651
                break;
132
651
              }
133
789
            if (!updated)
134
138
              variations->push_back ({tag, value});
135
789
            break;
136
806
          }
137
2.00k
        }
138
108
        break;
139
155
      }
140
141
317
      case HB_FUZZING_OP_SET_FLAGS:
142
317
      {
143
317
        uint32_t ignored;
144
317
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
2
          return false;
146
315
        break;
147
317
      }
148
149
432
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
432
        break;
151
152
274
      case HB_FUZZING_OP_SET_CLEAR:
153
711
      case HB_FUZZING_OP_SET_INVERT:
154
711
      {
155
711
        uint8_t ignored;
156
711
        if (!_fuzzing_read_value (p, end, &ignored))
157
3
          return false;
158
708
        break;
159
711
      }
160
161
708
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
47
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
47
      {
164
47
        uint8_t ignored_set_type;
165
47
        uint32_t count;
166
47
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
45
            !_fuzzing_read_u32_value (p, end, &count))
168
7
          return false;
169
792
        for (uint32_t i = 0; i < count; i++)
170
774
        {
171
774
          uint32_t ignored_start, ignored_end;
172
774
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
760
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
22
            return false;
175
774
        }
176
18
        break;
177
40
      }
178
179
47
      default:
180
47
        return false;
181
15.7k
    }
182
15.7k
  }
183
184
131
  return true;
185
305
}
hb-raster-fuzzer.cc:_fuzzing_apply_extended_shape_ops(hb_face_t*, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*, std::__1::vector<hb_variation_t, std::__1::allocator<hb_variation_t> >*, unsigned char const*, unsigned long)
Line
Count
Source
40
3
{
41
3
  variations->clear ();
42
3
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
3
  std::vector<hb_ot_var_axis_info_t> axes;
44
3
  if (axis_count)
45
1
  {
46
1
    axes.resize (axis_count);
47
1
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
1
  }
49
50
3
  const uint8_t *p = ops;
51
3
  const uint8_t *end = ops + ops_len;
52
6
  while (p < end)
53
3
  {
54
3
    uint8_t op;
55
3
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
3
    switch (op)
59
3
    {
60
3
      case HB_FUZZING_OP_TEXT_ADD:
61
3
      case HB_FUZZING_OP_TEXT_DEL:
62
3
      {
63
3
        uint32_t count;
64
3
        if (!_fuzzing_read_u32_value (p, end, &count))
65
0
          return false;
66
67
6
        for (uint32_t i = 0; i < count; i++)
68
3
        {
69
3
          uint32_t cp;
70
3
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
0
            return false;
72
3
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
3
            text->push_back (cp);
74
0
          else
75
0
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
3
        }
77
3
        break;
78
3
      }
79
80
3
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
0
        variations->clear ();
82
0
        break;
83
84
0
      case HB_FUZZING_OP_AXIS_SET:
85
0
      {
86
0
        uint32_t count;
87
0
        if (!_fuzzing_read_u32_value (p, end, &count))
88
0
          return false;
89
90
0
        for (uint32_t i = 0; i < count; i++)
91
0
        {
92
0
          uint32_t tag;
93
0
          uint8_t mode;
94
0
          float minimum, middle, maximum;
95
0
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
0
              !_fuzzing_read_value (p, end, &mode) ||
97
0
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
0
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
0
              !_fuzzing_read_f32_value (p, end, &maximum))
100
0
            return false;
101
102
0
          if (!axis_count)
103
0
            continue;
104
105
0
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
0
          {
107
0
            if (axes[axis_index].tag != tag)
108
0
              continue;
109
110
0
            float value = axes[axis_index].default_value;
111
0
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
0
              value = axes[axis_index].default_value;
113
0
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
0
            {
115
0
              if (!std::isnan (middle))
116
0
                value = middle;
117
0
              else if (!std::isnan (minimum))
118
0
                value = minimum;
119
0
              else if (!std::isnan (maximum))
120
0
                value = maximum;
121
0
            }
122
0
            else
123
0
              return false;
124
125
0
            bool updated = false;
126
0
            for (auto &variation : *variations)
127
0
              if (variation.tag == tag)
128
0
              {
129
0
                variation.value = value;
130
0
                updated = true;
131
0
                break;
132
0
              }
133
0
            if (!updated)
134
0
              variations->push_back ({tag, value});
135
0
            break;
136
0
          }
137
0
        }
138
0
        break;
139
0
      }
140
141
0
      case HB_FUZZING_OP_SET_FLAGS:
142
0
      {
143
0
        uint32_t ignored;
144
0
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
0
          return false;
146
0
        break;
147
0
      }
148
149
0
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
0
        break;
151
152
0
      case HB_FUZZING_OP_SET_CLEAR:
153
0
      case HB_FUZZING_OP_SET_INVERT:
154
0
      {
155
0
        uint8_t ignored;
156
0
        if (!_fuzzing_read_value (p, end, &ignored))
157
0
          return false;
158
0
        break;
159
0
      }
160
161
0
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
0
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
0
      {
164
0
        uint8_t ignored_set_type;
165
0
        uint32_t count;
166
0
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
0
            !_fuzzing_read_u32_value (p, end, &count))
168
0
          return false;
169
0
        for (uint32_t i = 0; i < count; i++)
170
0
        {
171
0
          uint32_t ignored_start, ignored_end;
172
0
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
0
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
0
            return false;
175
0
        }
176
0
        break;
177
0
      }
178
179
0
      default:
180
0
        return false;
181
3
    }
182
3
  }
183
184
3
  return true;
185
3
}
hb-gpu-fuzzer.cc:_fuzzing_apply_extended_shape_ops(hb_face_t*, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*, std::__1::vector<hb_variation_t, std::__1::allocator<hb_variation_t> >*, unsigned char const*, unsigned long)
Line
Count
Source
40
520
{
41
520
  variations->clear ();
42
520
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
520
  std::vector<hb_ot_var_axis_info_t> axes;
44
520
  if (axis_count)
45
176
  {
46
176
    axes.resize (axis_count);
47
176
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
176
  }
49
50
520
  const uint8_t *p = ops;
51
520
  const uint8_t *end = ops + ops_len;
52
3.69k
  while (p < end)
53
3.52k
  {
54
3.52k
    uint8_t op;
55
3.52k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
3.52k
    switch (op)
59
3.52k
    {
60
96
      case HB_FUZZING_OP_TEXT_ADD:
61
170
      case HB_FUZZING_OP_TEXT_DEL:
62
170
      {
63
170
        uint32_t count;
64
170
        if (!_fuzzing_read_u32_value (p, end, &count))
65
5
          return false;
66
67
20.0k
        for (uint32_t i = 0; i < count; i++)
68
19.9k
        {
69
19.9k
          uint32_t cp;
70
19.9k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
98
            return false;
72
19.8k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
15.2k
            text->push_back (cp);
74
4.67k
          else
75
4.67k
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
19.8k
        }
77
67
        break;
78
165
      }
79
80
641
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
641
        variations->clear ();
82
641
        break;
83
84
302
      case HB_FUZZING_OP_AXIS_SET:
85
302
      {
86
302
        uint32_t count;
87
302
        if (!_fuzzing_read_u32_value (p, end, &count))
88
2
          return false;
89
90
8.60k
        for (uint32_t i = 0; i < count; i++)
91
8.41k
        {
92
8.41k
          uint32_t tag;
93
8.41k
          uint8_t mode;
94
8.41k
          float minimum, middle, maximum;
95
8.41k
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
8.39k
              !_fuzzing_read_value (p, end, &mode) ||
97
8.39k
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
8.35k
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
8.34k
              !_fuzzing_read_f32_value (p, end, &maximum))
100
83
            return false;
101
102
8.33k
          if (!axis_count)
103
2.58k
            continue;
104
105
1.08M
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
1.08M
          {
107
1.08M
            if (axes[axis_index].tag != tag)
108
1.08M
              continue;
109
110
1.08k
            float value = axes[axis_index].default_value;
111
1.08k
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
470
              value = axes[axis_index].default_value;
113
618
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
595
            {
115
595
              if (!std::isnan (middle))
116
595
                value = middle;
117
0
              else if (!std::isnan (minimum))
118
0
                value = minimum;
119
0
              else if (!std::isnan (maximum))
120
0
                value = maximum;
121
595
            }
122
23
            else
123
23
              return false;
124
125
1.06k
            bool updated = false;
126
1.06k
            for (auto &variation : *variations)
127
2.01k
              if (variation.tag == tag)
128
848
              {
129
848
                variation.value = value;
130
848
                updated = true;
131
848
                break;
132
848
              }
133
1.06k
            if (!updated)
134
217
              variations->push_back ({tag, value});
135
1.06k
            break;
136
1.08k
          }
137
5.75k
        }
138
194
        break;
139
300
      }
140
141
873
      case HB_FUZZING_OP_SET_FLAGS:
142
873
      {
143
873
        uint32_t ignored;
144
873
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
9
          return false;
146
864
        break;
147
873
      }
148
149
864
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
717
        break;
151
152
274
      case HB_FUZZING_OP_SET_CLEAR:
153
664
      case HB_FUZZING_OP_SET_INVERT:
154
664
      {
155
664
        uint8_t ignored;
156
664
        if (!_fuzzing_read_value (p, end, &ignored))
157
2
          return false;
158
662
        break;
159
664
      }
160
161
662
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
91
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
91
      {
164
91
        uint8_t ignored_set_type;
165
91
        uint32_t count;
166
91
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
89
            !_fuzzing_read_u32_value (p, end, &count))
168
5
          return false;
169
8.37k
        for (uint32_t i = 0; i < count; i++)
170
8.34k
        {
171
8.34k
          uint32_t ignored_start, ignored_end;
172
8.34k
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
8.31k
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
55
            return false;
175
8.34k
        }
176
31
        break;
177
86
      }
178
179
66
      default:
180
66
        return false;
181
3.52k
    }
182
3.52k
  }
183
184
172
  return true;
185
520
}
hb-vector-fuzzer.cc:_fuzzing_apply_extended_shape_ops(hb_face_t*, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >*, std::__1::vector<hb_variation_t, std::__1::allocator<hb_variation_t> >*, unsigned char const*, unsigned long)
Line
Count
Source
40
523
{
41
523
  variations->clear ();
42
523
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
523
  std::vector<hb_ot_var_axis_info_t> axes;
44
523
  if (axis_count)
45
41
  {
46
41
    axes.resize (axis_count);
47
41
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
41
  }
49
50
523
  const uint8_t *p = ops;
51
523
  const uint8_t *end = ops + ops_len;
52
4.49k
  while (p < end)
53
4.07k
  {
54
4.07k
    uint8_t op;
55
4.07k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
4.07k
    switch (op)
59
4.07k
    {
60
495
      case HB_FUZZING_OP_TEXT_ADD:
61
534
      case HB_FUZZING_OP_TEXT_DEL:
62
534
      {
63
534
        uint32_t count;
64
534
        if (!_fuzzing_read_u32_value (p, end, &count))
65
4
          return false;
66
67
2.60k
        for (uint32_t i = 0; i < count; i++)
68
2.10k
        {
69
2.10k
          uint32_t cp;
70
2.10k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
28
            return false;
72
2.07k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
1.71k
            text->push_back (cp);
74
366
          else
75
366
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
2.07k
        }
77
502
        break;
78
530
      }
79
80
502
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
153
        variations->clear ();
82
153
        break;
83
84
53
      case HB_FUZZING_OP_AXIS_SET:
85
53
      {
86
53
        uint32_t count;
87
53
        if (!_fuzzing_read_u32_value (p, end, &count))
88
2
          return false;
89
90
352
        for (uint32_t i = 0; i < count; i++)
91
319
        {
92
319
          uint32_t tag;
93
319
          uint8_t mode;
94
319
          float minimum, middle, maximum;
95
319
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
313
              !_fuzzing_read_value (p, end, &mode) ||
97
312
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
309
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
305
              !_fuzzing_read_f32_value (p, end, &maximum))
100
17
            return false;
101
102
302
          if (!axis_count)
103
268
            continue;
104
105
60
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
54
          {
107
54
            if (axes[axis_index].tag != tag)
108
26
              continue;
109
110
28
            float value = axes[axis_index].default_value;
111
28
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
1
              value = axes[axis_index].default_value;
113
27
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
26
            {
115
26
              if (!std::isnan (middle))
116
25
                value = middle;
117
1
              else if (!std::isnan (minimum))
118
1
                value = minimum;
119
0
              else if (!std::isnan (maximum))
120
0
                value = maximum;
121
26
            }
122
1
            else
123
1
              return false;
124
125
27
            bool updated = false;
126
27
            for (auto &variation : *variations)
127
12
              if (variation.tag == tag)
128
0
              {
129
0
                variation.value = value;
130
0
                updated = true;
131
0
                break;
132
0
              }
133
27
            if (!updated)
134
27
              variations->push_back ({tag, value});
135
27
            break;
136
28
          }
137
34
        }
138
33
        break;
139
51
      }
140
141
193
      case HB_FUZZING_OP_SET_FLAGS:
142
193
      {
143
193
        uint32_t ignored;
144
193
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
2
          return false;
146
191
        break;
147
193
      }
148
149
2.35k
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
2.35k
        break;
151
152
601
      case HB_FUZZING_OP_SET_CLEAR:
153
715
      case HB_FUZZING_OP_SET_INVERT:
154
715
      {
155
715
        uint8_t ignored;
156
715
        if (!_fuzzing_read_value (p, end, &ignored))
157
1
          return false;
158
714
        break;
159
715
      }
160
161
714
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
31
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
31
      {
164
31
        uint8_t ignored_set_type;
165
31
        uint32_t count;
166
31
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
30
            !_fuzzing_read_u32_value (p, end, &count))
168
2
          return false;
169
547
        for (uint32_t i = 0; i < count; i++)
170
531
        {
171
531
          uint32_t ignored_start, ignored_end;
172
531
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
523
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
13
            return false;
175
531
        }
176
16
        break;
177
29
      }
178
179
33
      default:
180
33
        return false;
181
4.07k
    }
182
4.07k
  }
183
184
420
  return true;
185
523
}
186
187
static bool
188
_fuzzing_extract_extended_ops (const uint8_t *data,
189
                               size_t size,
190
                               size_t *font_len,
191
                               const uint8_t **ops,
192
                               size_t *ops_len)
193
81.9k
{
194
81.9k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
3.12k
    return false;
196
197
78.8k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
78.8k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
77.4k
    return false;
200
201
1.41k
  size_t ops_len_offset = magic_offset - 4;
202
1.41k
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
1.41k
  if (parsed_ops_len > ops_len_offset)
204
66
    return false;
205
206
1.35k
  *font_len = ops_len_offset - parsed_ops_len;
207
1.35k
  *ops = data + *font_len;
208
1.35k
  *ops_len = parsed_ops_len;
209
1.35k
  return true;
210
1.41k
}
hb-shape-fuzzer.cc:_fuzzing_extract_extended_ops(unsigned char const*, unsigned long, unsigned long*, unsigned char const**, unsigned long*)
Line
Count
Source
193
37.8k
{
194
37.8k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
1.96k
    return false;
196
197
35.8k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
35.8k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
35.5k
    return false;
200
201
317
  size_t ops_len_offset = magic_offset - 4;
202
317
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
317
  if (parsed_ops_len > ops_len_offset)
204
12
    return false;
205
206
305
  *font_len = ops_len_offset - parsed_ops_len;
207
305
  *ops = data + *font_len;
208
305
  *ops_len = parsed_ops_len;
209
305
  return true;
210
317
}
hb-raster-fuzzer.cc:_fuzzing_extract_extended_ops(unsigned char const*, unsigned long, unsigned long*, unsigned char const**, unsigned long*)
Line
Count
Source
193
793
{
194
793
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
0
    return false;
196
197
793
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
793
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
788
    return false;
200
201
5
  size_t ops_len_offset = magic_offset - 4;
202
5
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
5
  if (parsed_ops_len > ops_len_offset)
204
2
    return false;
205
206
3
  *font_len = ops_len_offset - parsed_ops_len;
207
3
  *ops = data + *font_len;
208
3
  *ops_len = parsed_ops_len;
209
3
  return true;
210
5
}
hb-gpu-fuzzer.cc:_fuzzing_extract_extended_ops(unsigned char const*, unsigned long, unsigned long*, unsigned char const**, unsigned long*)
Line
Count
Source
193
14.8k
{
194
14.8k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
328
    return false;
196
197
14.5k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
14.5k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
13.9k
    return false;
200
201
565
  size_t ops_len_offset = magic_offset - 4;
202
565
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
565
  if (parsed_ops_len > ops_len_offset)
204
45
    return false;
205
206
520
  *font_len = ops_len_offset - parsed_ops_len;
207
520
  *ops = data + *font_len;
208
520
  *ops_len = parsed_ops_len;
209
520
  return true;
210
565
}
hb-vector-fuzzer.cc:_fuzzing_extract_extended_ops(unsigned char const*, unsigned long, unsigned long*, unsigned char const**, unsigned long*)
Line
Count
Source
193
28.4k
{
194
28.4k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
834
    return false;
196
197
27.5k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
27.5k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
27.0k
    return false;
200
201
530
  size_t ops_len_offset = magic_offset - 4;
202
530
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
530
  if (parsed_ops_len > ops_len_offset)
204
7
    return false;
205
206
523
  *font_len = ops_len_offset - parsed_ops_len;
207
523
  *ops = data + *font_len;
208
523
  *ops_len = parsed_ops_len;
209
523
  return true;
210
530
}
211
212
static _fuzzing_shape_input_status_t
213
_fuzzing_prepare_shape_input (const uint8_t *data,
214
                              size_t size,
215
                              int x_scale,
216
                              int y_scale,
217
                              _fuzzing_shape_input_t *input)
218
81.9k
{
219
81.9k
  size_t font_len = 0;
220
81.9k
  const uint8_t *ops = nullptr;
221
81.9k
  size_t ops_len = 0;
222
81.9k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
81.9k
  input->blob = hb_blob_create ((const char *) data,
225
81.9k
                                is_extended ? font_len : size,
226
81.9k
                                HB_MEMORY_MODE_READONLY,
227
81.9k
                                nullptr, nullptr);
228
81.9k
  input->face = hb_face_create (input->blob, 0);
229
81.9k
  input->font = hb_font_create (input->face);
230
81.9k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
81.9k
  if (is_extended)
233
1.35k
  {
234
1.35k
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
625
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
726
    hb_font_set_variations (input->font,
238
726
                            input->variations.empty () ? nullptr : input->variations.data (),
239
726
                            input->variations.size ());
240
726
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
1.35k
  }
242
243
80.5k
  unsigned num_coords = 0;
244
80.5k
  if (size)
245
80.5k
    num_coords = data[size - 1];
246
80.5k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
80.5k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
80.5k
  if (size > num_coords + 1)
249
129k
    for (unsigned i = 0; i < num_coords; ++i)
250
49.2k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
80.5k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
80.5k
  free (coords);
253
254
80.5k
  uint32_t text32[16] = {0};
255
80.5k
  unsigned int len = sizeof (text32);
256
80.5k
  if (size < len)
257
10.7k
    len = size;
258
80.5k
  if (len)
259
80.5k
    memcpy (text32, data + size - len, len);
260
261
80.5k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
80.5k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
81.9k
}
hb-shape-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
37.8k
{
219
37.8k
  size_t font_len = 0;
220
37.8k
  const uint8_t *ops = nullptr;
221
37.8k
  size_t ops_len = 0;
222
37.8k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
37.8k
  input->blob = hb_blob_create ((const char *) data,
225
37.8k
                                is_extended ? font_len : size,
226
37.8k
                                HB_MEMORY_MODE_READONLY,
227
37.8k
                                nullptr, nullptr);
228
37.8k
  input->face = hb_face_create (input->blob, 0);
229
37.8k
  input->font = hb_font_create (input->face);
230
37.8k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
37.8k
  if (is_extended)
233
305
  {
234
305
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
174
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
131
    hb_font_set_variations (input->font,
238
131
                            input->variations.empty () ? nullptr : input->variations.data (),
239
131
                            input->variations.size ());
240
131
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
305
  }
242
243
37.5k
  unsigned num_coords = 0;
244
37.5k
  if (size)
245
37.5k
    num_coords = data[size - 1];
246
37.5k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
37.5k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
37.5k
  if (size > num_coords + 1)
249
44.3k
    for (unsigned i = 0; i < num_coords; ++i)
250
6.87k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
37.5k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
37.5k
  free (coords);
253
254
37.5k
  uint32_t text32[16] = {0};
255
37.5k
  unsigned int len = sizeof (text32);
256
37.5k
  if (size < len)
257
6.66k
    len = size;
258
37.5k
  if (len)
259
37.5k
    memcpy (text32, data + size - len, len);
260
261
37.5k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
37.5k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
37.8k
}
hb-raster-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
793
{
219
793
  size_t font_len = 0;
220
793
  const uint8_t *ops = nullptr;
221
793
  size_t ops_len = 0;
222
793
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
793
  input->blob = hb_blob_create ((const char *) data,
225
793
                                is_extended ? font_len : size,
226
793
                                HB_MEMORY_MODE_READONLY,
227
793
                                nullptr, nullptr);
228
793
  input->face = hb_face_create (input->blob, 0);
229
793
  input->font = hb_font_create (input->face);
230
793
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
793
  if (is_extended)
233
3
  {
234
3
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
0
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
3
    hb_font_set_variations (input->font,
238
3
                            input->variations.empty () ? nullptr : input->variations.data (),
239
3
                            input->variations.size ());
240
3
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
3
  }
242
243
790
  unsigned num_coords = 0;
244
790
  if (size)
245
790
    num_coords = data[size - 1];
246
790
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
790
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
790
  if (size > num_coords + 1)
249
1.30k
    for (unsigned i = 0; i < num_coords; ++i)
250
514
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
790
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
790
  free (coords);
253
254
790
  uint32_t text32[16] = {0};
255
790
  unsigned int len = sizeof (text32);
256
790
  if (size < len)
257
0
    len = size;
258
790
  if (len)
259
790
    memcpy (text32, data + size - len, len);
260
261
790
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
790
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
793
}
hb-gpu-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
14.8k
{
219
14.8k
  size_t font_len = 0;
220
14.8k
  const uint8_t *ops = nullptr;
221
14.8k
  size_t ops_len = 0;
222
14.8k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
14.8k
  input->blob = hb_blob_create ((const char *) data,
225
14.8k
                                is_extended ? font_len : size,
226
14.8k
                                HB_MEMORY_MODE_READONLY,
227
14.8k
                                nullptr, nullptr);
228
14.8k
  input->face = hb_face_create (input->blob, 0);
229
14.8k
  input->font = hb_font_create (input->face);
230
14.8k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
14.8k
  if (is_extended)
233
520
  {
234
520
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
348
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
172
    hb_font_set_variations (input->font,
238
172
                            input->variations.empty () ? nullptr : input->variations.data (),
239
172
                            input->variations.size ());
240
172
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
520
  }
242
243
14.3k
  unsigned num_coords = 0;
244
14.3k
  if (size)
245
14.3k
    num_coords = data[size - 1];
246
14.3k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
14.3k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
14.3k
  if (size > num_coords + 1)
249
29.8k
    for (unsigned i = 0; i < num_coords; ++i)
250
15.4k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
14.3k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
14.3k
  free (coords);
253
254
14.3k
  uint32_t text32[16] = {0};
255
14.3k
  unsigned int len = sizeof (text32);
256
14.3k
  if (size < len)
257
736
    len = size;
258
14.3k
  if (len)
259
14.3k
    memcpy (text32, data + size - len, len);
260
261
14.3k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
14.3k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
14.8k
}
hb-vector-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
28.4k
{
219
28.4k
  size_t font_len = 0;
220
28.4k
  const uint8_t *ops = nullptr;
221
28.4k
  size_t ops_len = 0;
222
28.4k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
28.4k
  input->blob = hb_blob_create ((const char *) data,
225
28.4k
                                is_extended ? font_len : size,
226
28.4k
                                HB_MEMORY_MODE_READONLY,
227
28.4k
                                nullptr, nullptr);
228
28.4k
  input->face = hb_face_create (input->blob, 0);
229
28.4k
  input->font = hb_font_create (input->face);
230
28.4k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
28.4k
  if (is_extended)
233
523
  {
234
523
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
103
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
420
    hb_font_set_variations (input->font,
238
420
                            input->variations.empty () ? nullptr : input->variations.data (),
239
420
                            input->variations.size ());
240
420
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
523
  }
242
243
27.8k
  unsigned num_coords = 0;
244
27.8k
  if (size)
245
27.8k
    num_coords = data[size - 1];
246
27.8k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
27.8k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
27.8k
  if (size > num_coords + 1)
249
54.2k
    for (unsigned i = 0; i < num_coords; ++i)
250
26.4k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
27.8k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
27.8k
  free (coords);
253
254
27.8k
  uint32_t text32[16] = {0};
255
27.8k
  unsigned int len = sizeof (text32);
256
27.8k
  if (size < len)
257
3.30k
    len = size;
258
27.8k
  if (len)
259
27.8k
    memcpy (text32, data + size - len, len);
260
261
27.8k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
27.8k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
28.4k
}
264