Coverage Report

Created: 2026-06-13 06:37

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.7k
  {
28
81.7k
    hb_font_destroy (font);
29
81.7k
    hb_face_destroy (face);
30
81.7k
    hb_blob_destroy (blob);
31
81.7k
  }
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.38k
{
41
1.38k
  variations->clear ();
42
1.38k
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
1.38k
  std::vector<hb_ot_var_axis_info_t> axes;
44
1.38k
  if (axis_count)
45
348
  {
46
348
    axes.resize (axis_count);
47
348
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
348
  }
49
50
1.38k
  const uint8_t *p = ops;
51
1.38k
  const uint8_t *end = ops + ops_len;
52
26.5k
  while (p < end)
53
25.7k
  {
54
25.7k
    uint8_t op;
55
25.7k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
25.7k
    switch (op)
59
25.7k
    {
60
664
      case HB_FUZZING_OP_TEXT_ADD:
61
816
      case HB_FUZZING_OP_TEXT_DEL:
62
816
      {
63
816
        uint32_t count;
64
816
        if (!_fuzzing_read_u32_value (p, end, &count))
65
11
          return false;
66
67
25.0k
        for (uint32_t i = 0; i < count; i++)
68
24.4k
        {
69
24.4k
          uint32_t cp;
70
24.4k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
160
            return false;
72
24.2k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
18.0k
            text->push_back (cp);
74
6.26k
          else
75
6.26k
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
24.2k
        }
77
645
        break;
78
805
      }
79
80
17.0k
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
17.0k
        variations->clear ();
82
17.0k
        break;
83
84
527
      case HB_FUZZING_OP_AXIS_SET:
85
527
      {
86
527
        uint32_t count;
87
527
        if (!_fuzzing_read_u32_value (p, end, &count))
88
5
          return false;
89
90
11.8k
        for (uint32_t i = 0; i < count; i++)
91
11.4k
        {
92
11.4k
          uint32_t tag;
93
11.4k
          uint8_t mode;
94
11.4k
          float minimum, middle, maximum;
95
11.4k
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
11.4k
              !_fuzzing_read_value (p, end, &mode) ||
97
11.4k
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
11.4k
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
11.3k
              !_fuzzing_read_f32_value (p, end, &maximum))
100
141
            return false;
101
102
11.3k
          if (!axis_count)
103
3.23k
            continue;
104
105
1.13M
          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.89k
            float value = axes[axis_index].default_value;
111
1.89k
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
927
              value = axes[axis_index].default_value;
113
971
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
930
            {
115
930
              if (!std::isnan (middle))
116
909
                value = middle;
117
21
              else if (!std::isnan (minimum))
118
8
                value = minimum;
119
13
              else if (!std::isnan (maximum))
120
10
                value = maximum;
121
930
            }
122
41
            else
123
41
              return false;
124
125
1.85k
            bool updated = false;
126
1.85k
            for (auto &variation : *variations)
127
2.94k
              if (variation.tag == tag)
128
1.46k
              {
129
1.46k
                variation.value = value;
130
1.46k
                updated = true;
131
1.46k
                break;
132
1.46k
              }
133
1.85k
            if (!updated)
134
388
              variations->push_back ({tag, value});
135
1.85k
            break;
136
1.89k
          }
137
8.12k
        }
138
340
        break;
139
522
      }
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
15
          return false;
146
1.36k
        break;
147
1.38k
      }
148
149
3.66k
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
3.66k
        break;
151
152
1.15k
      case HB_FUZZING_OP_SET_CLEAR:
153
1.98k
      case HB_FUZZING_OP_SET_INVERT:
154
1.98k
      {
155
1.98k
        uint8_t ignored;
156
1.98k
        if (!_fuzzing_read_value (p, end, &ignored))
157
5
          return false;
158
1.98k
        break;
159
1.98k
      }
160
161
1.98k
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
158
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
158
      {
164
158
        uint8_t ignored_set_type;
165
158
        uint32_t count;
166
158
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
154
            !_fuzzing_read_u32_value (p, end, &count))
168
10
          return false;
169
9.17k
        for (uint32_t i = 0; i < count; i++)
170
9.11k
        {
171
9.11k
          uint32_t ignored_start, ignored_end;
172
9.11k
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
9.07k
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
88
            return false;
175
9.11k
        }
176
60
        break;
177
148
      }
178
179
169
      default:
180
169
        return false;
181
25.7k
    }
182
25.7k
  }
183
184
735
  return true;
185
1.38k
}
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
327
{
41
327
  variations->clear ();
42
327
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
327
  std::vector<hb_ot_var_axis_info_t> axes;
44
327
  if (axis_count)
45
129
  {
46
129
    axes.resize (axis_count);
47
129
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
129
  }
49
50
327
  const uint8_t *p = ops;
51
327
  const uint8_t *end = ops + ops_len;
52
18.3k
  while (p < end)
53
18.1k
  {
54
18.1k
    uint8_t op;
55
18.1k
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
18.1k
    switch (op)
59
18.1k
    {
60
64
      case HB_FUZZING_OP_TEXT_ADD:
61
103
      case HB_FUZZING_OP_TEXT_DEL:
62
103
      {
63
103
        uint32_t count;
64
103
        if (!_fuzzing_read_u32_value (p, end, &count))
65
2
          return false;
66
67
2.39k
        for (uint32_t i = 0; i < count; i++)
68
2.32k
        {
69
2.32k
          uint32_t cp;
70
2.32k
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
34
            return false;
72
2.29k
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
1.06k
            text->push_back (cp);
74
1.22k
          else
75
1.22k
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
2.29k
        }
77
67
        break;
78
101
      }
79
80
16.2k
      case HB_FUZZING_OP_AXIS_PIN_ALL_TO_DEFAULT:
81
16.2k
        variations->clear ();
82
16.2k
        break;
83
84
172
      case HB_FUZZING_OP_AXIS_SET:
85
172
      {
86
172
        uint32_t count;
87
172
        if (!_fuzzing_read_u32_value (p, end, &count))
88
1
          return false;
89
90
2.88k
        for (uint32_t i = 0; i < count; i++)
91
2.76k
        {
92
2.76k
          uint32_t tag;
93
2.76k
          uint8_t mode;
94
2.76k
          float minimum, middle, maximum;
95
2.76k
          if (!_fuzzing_read_u32_value (p, end, &tag) ||
96
2.75k
              !_fuzzing_read_value (p, end, &mode) ||
97
2.75k
              !_fuzzing_read_f32_value (p, end, &minimum) ||
98
2.74k
              !_fuzzing_read_f32_value (p, end, &middle) ||
99
2.73k
              !_fuzzing_read_f32_value (p, end, &maximum))
100
41
            return false;
101
102
2.72k
          if (!axis_count)
103
387
            continue;
104
105
49.5k
          for (unsigned axis_index = 0; axis_index < axis_count; axis_index++)
106
47.9k
          {
107
47.9k
            if (axes[axis_index].tag != tag)
108
47.2k
              continue;
109
110
782
            float value = axes[axis_index].default_value;
111
782
            if (mode == HB_FUZZING_AXIS_PIN_TO_DEFAULT)
112
456
              value = axes[axis_index].default_value;
113
326
            else if (mode == HB_FUZZING_AXIS_SET_RANGE)
114
309
            {
115
309
              if (!std::isnan (middle))
116
289
                value = middle;
117
20
              else if (!std::isnan (minimum))
118
7
                value = minimum;
119
13
              else if (!std::isnan (maximum))
120
10
                value = maximum;
121
309
            }
122
17
            else
123
17
              return false;
124
125
765
            bool updated = false;
126
765
            for (auto &variation : *variations)
127
917
              if (variation.tag == tag)
128
621
              {
129
621
                variation.value = value;
130
621
                updated = true;
131
621
                break;
132
621
              }
133
765
            if (!updated)
134
144
              variations->push_back ({tag, value});
135
765
            break;
136
782
          }
137
2.33k
        }
138
113
        break;
139
171
      }
140
141
316
      case HB_FUZZING_OP_SET_FLAGS:
142
316
      {
143
316
        uint32_t ignored;
144
316
        if (!_fuzzing_read_u32_value (p, end, &ignored))
145
4
          return false;
146
312
        break;
147
316
      }
148
149
590
      case HB_FUZZING_OP_KEEP_EVERYTHING:
150
590
        break;
151
152
276
      case HB_FUZZING_OP_SET_CLEAR:
153
606
      case HB_FUZZING_OP_SET_INVERT:
154
606
      {
155
606
        uint8_t ignored;
156
606
        if (!_fuzzing_read_value (p, end, &ignored))
157
2
          return false;
158
604
        break;
159
606
      }
160
161
604
      case HB_FUZZING_OP_SET_ADD_RANGES:
162
36
      case HB_FUZZING_OP_SET_DEL_RANGES:
163
36
      {
164
36
        uint8_t ignored_set_type;
165
36
        uint32_t count;
166
36
        if (!_fuzzing_read_value (p, end, &ignored_set_type) ||
167
35
            !_fuzzing_read_u32_value (p, end, &count))
168
3
          return false;
169
260
        for (uint32_t i = 0; i < count; i++)
170
247
        {
171
247
          uint32_t ignored_start, ignored_end;
172
247
          if (!_fuzzing_read_u32_value (p, end, &ignored_start) ||
173
234
              !_fuzzing_read_u32_value (p, end, &ignored_end))
174
20
            return false;
175
247
        }
176
13
        break;
177
33
      }
178
179
69
      default:
180
69
        return false;
181
18.1k
    }
182
18.1k
  }
183
184
134
  return true;
185
327
}
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
10
{
41
10
  variations->clear ();
42
10
  unsigned axis_count = hb_ot_var_get_axis_count (face);
43
10
  std::vector<hb_ot_var_axis_info_t> axes;
44
10
  if (axis_count)
45
2
  {
46
2
    axes.resize (axis_count);
47
2
    (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axes.data ());
48
2
  }
49
50
10
  const uint8_t *p = ops;
51
10
  const uint8_t *end = ops + ops_len;
52
19
  while (p < end)
53
10
  {
54
10
    uint8_t op;
55
10
    if (!_fuzzing_read_value (p, end, &op))
56
0
      return false;
57
58
10
    switch (op)
59
10
    {
60
9
      case HB_FUZZING_OP_TEXT_ADD:
61
9
      case HB_FUZZING_OP_TEXT_DEL:
62
9
      {
63
9
        uint32_t count;
64
9
        if (!_fuzzing_read_u32_value (p, end, &count))
65
0
          return false;
66
67
18
        for (uint32_t i = 0; i < count; i++)
68
9
        {
69
9
          uint32_t cp;
70
9
          if (!_fuzzing_read_u32_value (p, end, &cp))
71
0
            return false;
72
9
          if (op == HB_FUZZING_OP_TEXT_ADD)
73
9
            text->push_back (cp);
74
0
          else
75
0
            text->erase (std::remove (text->begin (), text->end (), cp), text->end ());
76
9
        }
77
9
        break;
78
9
      }
79
80
9
      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
1
      default:
180
1
        return false;
181
10
    }
182
10
  }
183
184
9
  return true;
185
10
}
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.7k
{
194
81.7k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
3.09k
    return false;
196
197
78.6k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
78.6k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
77.2k
    return false;
200
201
1.45k
  size_t ops_len_offset = magic_offset - 4;
202
1.45k
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
1.45k
  if (parsed_ops_len > ops_len_offset)
204
78
    return false;
205
206
1.38k
  *font_len = ops_len_offset - parsed_ops_len;
207
1.38k
  *ops = data + *font_len;
208
1.38k
  *ops_len = parsed_ops_len;
209
1.38k
  return true;
210
1.45k
}
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.0k
{
194
37.0k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
1.93k
    return false;
196
197
35.1k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
35.1k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
34.8k
    return false;
200
201
351
  size_t ops_len_offset = magic_offset - 4;
202
351
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
351
  if (parsed_ops_len > ops_len_offset)
204
24
    return false;
205
206
327
  *font_len = ops_len_offset - parsed_ops_len;
207
327
  *ops = data + *font_len;
208
327
  *ops_len = parsed_ops_len;
209
327
  return true;
210
351
}
hb-raster-fuzzer.cc:_fuzzing_extract_extended_ops(unsigned char const*, unsigned long, unsigned long*, unsigned char const**, unsigned long*)
Line
Count
Source
193
1.37k
{
194
1.37k
  if (size < sizeof (_fuzzing_extended_magic) + 4)
195
0
    return false;
196
197
1.37k
  size_t magic_offset = size - sizeof (_fuzzing_extended_magic);
198
1.37k
  if (0 != memcmp (data + magic_offset, _fuzzing_extended_magic, sizeof (_fuzzing_extended_magic)))
199
1.36k
    return false;
200
201
12
  size_t ops_len_offset = magic_offset - 4;
202
12
  uint32_t parsed_ops_len = _fuzzing_read_u32_le (data + ops_len_offset);
203
12
  if (parsed_ops_len > ops_len_offset)
204
2
    return false;
205
206
10
  *font_len = ops_len_offset - parsed_ops_len;
207
10
  *ops = data + *font_len;
208
10
  *ops_len = parsed_ops_len;
209
10
  return true;
210
12
}
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.7k
{
219
81.7k
  size_t font_len = 0;
220
81.7k
  const uint8_t *ops = nullptr;
221
81.7k
  size_t ops_len = 0;
222
81.7k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
81.7k
  input->blob = hb_blob_create ((const char *) data,
225
81.7k
                                is_extended ? font_len : size,
226
81.7k
                                HB_MEMORY_MODE_READONLY,
227
81.7k
                                nullptr, nullptr);
228
81.7k
  input->face = hb_face_create (input->blob, 0);
229
81.7k
  input->font = hb_font_create (input->face);
230
81.7k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
81.7k
  if (is_extended)
233
1.38k
  {
234
1.38k
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
645
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
735
    hb_font_set_variations (input->font,
238
735
                            input->variations.empty () ? nullptr : input->variations.data (),
239
735
                            input->variations.size ());
240
735
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
1.38k
  }
242
243
80.3k
  unsigned num_coords = 0;
244
80.3k
  if (size)
245
80.3k
    num_coords = data[size - 1];
246
80.3k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
80.3k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
80.3k
  if (size > num_coords + 1)
249
132k
    for (unsigned i = 0; i < num_coords; ++i)
250
52.6k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
80.3k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
80.3k
  free (coords);
253
254
80.3k
  uint32_t text32[16] = {0};
255
80.3k
  unsigned int len = sizeof (text32);
256
80.3k
  if (size < len)
257
10.5k
    len = size;
258
80.3k
  if (len)
259
80.3k
    memcpy (text32, data + size - len, len);
260
261
80.3k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
80.3k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
81.7k
}
hb-shape-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
37.0k
{
219
37.0k
  size_t font_len = 0;
220
37.0k
  const uint8_t *ops = nullptr;
221
37.0k
  size_t ops_len = 0;
222
37.0k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
37.0k
  input->blob = hb_blob_create ((const char *) data,
225
37.0k
                                is_extended ? font_len : size,
226
37.0k
                                HB_MEMORY_MODE_READONLY,
227
37.0k
                                nullptr, nullptr);
228
37.0k
  input->face = hb_face_create (input->blob, 0);
229
37.0k
  input->font = hb_font_create (input->face);
230
37.0k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
37.0k
  if (is_extended)
233
327
  {
234
327
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
193
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
134
    hb_font_set_variations (input->font,
238
134
                            input->variations.empty () ? nullptr : input->variations.data (),
239
134
                            input->variations.size ());
240
134
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
327
  }
242
243
36.7k
  unsigned num_coords = 0;
244
36.7k
  if (size)
245
36.7k
    num_coords = data[size - 1];
246
36.7k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
36.7k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
36.7k
  if (size > num_coords + 1)
249
41.9k
    for (unsigned i = 0; i < num_coords; ++i)
250
5.23k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
36.7k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
36.7k
  free (coords);
253
254
36.7k
  uint32_t text32[16] = {0};
255
36.7k
  unsigned int len = sizeof (text32);
256
36.7k
  if (size < len)
257
6.49k
    len = size;
258
36.7k
  if (len)
259
36.7k
    memcpy (text32, data + size - len, len);
260
261
36.7k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
36.7k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
37.0k
}
hb-raster-fuzzer.cc:_fuzzing_prepare_shape_input(unsigned char const*, unsigned long, int, int, _fuzzing_shape_input_t*)
Line
Count
Source
218
1.37k
{
219
1.37k
  size_t font_len = 0;
220
1.37k
  const uint8_t *ops = nullptr;
221
1.37k
  size_t ops_len = 0;
222
1.37k
  bool is_extended = _fuzzing_extract_extended_ops (data, size, &font_len, &ops, &ops_len);
223
224
1.37k
  input->blob = hb_blob_create ((const char *) data,
225
1.37k
                                is_extended ? font_len : size,
226
1.37k
                                HB_MEMORY_MODE_READONLY,
227
1.37k
                                nullptr, nullptr);
228
1.37k
  input->face = hb_face_create (input->blob, 0);
229
1.37k
  input->font = hb_font_create (input->face);
230
1.37k
  hb_font_set_scale (input->font, x_scale, y_scale);
231
232
1.37k
  if (is_extended)
233
10
  {
234
10
    if (!_fuzzing_apply_extended_shape_ops (input->face, &input->text, &input->variations, ops, ops_len))
235
1
      return HB_FUZZING_SHAPE_INPUT_MALFORMED;
236
237
9
    hb_font_set_variations (input->font,
238
9
                            input->variations.empty () ? nullptr : input->variations.data (),
239
9
                            input->variations.size ());
240
9
    return HB_FUZZING_SHAPE_INPUT_EXTENDED;
241
10
  }
242
243
1.36k
  unsigned num_coords = 0;
244
1.36k
  if (size)
245
1.36k
    num_coords = data[size - 1];
246
1.36k
  num_coords = hb_ot_var_get_axis_count (input->face) > num_coords ? num_coords : hb_ot_var_get_axis_count (input->face);
247
1.36k
  int *coords = (int *) calloc (num_coords, sizeof (int));
248
1.36k
  if (size > num_coords + 1)
249
6.88k
    for (unsigned i = 0; i < num_coords; ++i)
250
5.52k
      coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
251
1.36k
  hb_font_set_var_coords_normalized (input->font, coords, num_coords);
252
1.36k
  free (coords);
253
254
1.36k
  uint32_t text32[16] = {0};
255
1.36k
  unsigned int len = sizeof (text32);
256
1.36k
  if (size < len)
257
0
    len = size;
258
1.36k
  if (len)
259
1.36k
    memcpy (text32, data + size - len, len);
260
261
1.36k
  input->text.assign (text32, text32 + sizeof (text32) / sizeof (text32[0]));
262
1.36k
  return HB_FUZZING_SHAPE_INPUT_RAW;
263
1.37k
}
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