1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include <hb-ot.h>
5
6 #include "hb-fuzzer.hh"
7
8 #ifdef HB_EXPERIMENTAL_API
9 struct _user_data_t
10 {
11 bool is_open;
12 unsigned path_len;
13 hb_position_t path_start_x;
14 hb_position_t path_start_y;
15 hb_position_t path_last_x;
16 hb_position_t path_last_y;
17 };
18
19 static void
_move_to(hb_position_t to_x,hb_position_t to_y,void * user_data_)20 _move_to (hb_position_t to_x, hb_position_t to_y, void *user_data_)
21 {
22 _user_data_t *user_data = (_user_data_t *) user_data_;
23 assert (!user_data->is_open);
24 user_data->is_open = true;
25 user_data->path_start_x = user_data->path_last_x = to_x;
26 user_data->path_start_y = user_data->path_last_y = to_y;
27 }
28
29 static void
_line_to(hb_position_t to_x,hb_position_t to_y,void * user_data_)30 _line_to (hb_position_t to_x, hb_position_t to_y, void *user_data_)
31 {
32 _user_data_t *user_data = (_user_data_t *) user_data_;
33 assert (user_data->is_open);
34 assert (user_data->path_last_x != to_x || user_data->path_last_y != to_y);
35 ++user_data->path_len;
36 user_data->path_last_x = to_x;
37 user_data->path_last_y = to_y;
38 }
39
40 static void
_quadratic_to(hb_position_t control_x,hb_position_t control_y,hb_position_t to_x,hb_position_t to_y,void * user_data_)41 _quadratic_to (hb_position_t control_x, hb_position_t control_y,
42 hb_position_t to_x, hb_position_t to_y, void *user_data_)
43 {
44 _user_data_t *user_data = (_user_data_t *) user_data_;
45 assert (user_data->is_open);
46 assert (user_data->path_last_x != control_x || user_data->path_last_y != control_y ||
47 user_data->path_last_x != to_x || user_data->path_last_y != to_y);
48 ++user_data->path_len;
49 user_data->path_last_x = to_x;
50 user_data->path_last_y = to_y;
51 }
52
53 static void
_cubic_to(hb_position_t control1_x,hb_position_t control1_y,hb_position_t control2_x,hb_position_t control2_y,hb_position_t to_x,hb_position_t to_y,void * user_data_)54 _cubic_to (hb_position_t control1_x, hb_position_t control1_y,
55 hb_position_t control2_x, hb_position_t control2_y,
56 hb_position_t to_x, hb_position_t to_y, void *user_data_)
57 {
58 _user_data_t *user_data = (_user_data_t *) user_data_;
59 assert (user_data->is_open);
60 assert (user_data->path_last_x != control1_x || user_data->path_last_y != control1_y ||
61 user_data->path_last_x != control2_x || user_data->path_last_y != control2_y ||
62 user_data->path_last_x != to_x || user_data->path_last_y != to_y);
63 ++user_data->path_len;
64 user_data->path_last_x = to_x;
65 user_data->path_last_y = to_y;
66 }
67
68 static void
_close_path(void * user_data_)69 _close_path (void *user_data_)
70 {
71 _user_data_t *user_data = (_user_data_t *) user_data_;
72 assert (user_data->is_open && user_data->path_len != 0);
73 user_data->path_len = 0;
74 user_data->is_open = false;
75 assert (user_data->path_start_x == user_data->path_last_x &&
76 user_data->path_start_y == user_data->path_last_y);
77 }
78 #endif
79
80 /* Similar to test-ot-face.c's #test_font() */
misc_calls_for_gid(hb_face_t * face,hb_font_t * font,hb_set_t * set,hb_codepoint_t cp)81 static void misc_calls_for_gid (hb_face_t *face, hb_font_t *font, hb_set_t *set, hb_codepoint_t cp)
82 {
83 /* Other gid specific misc calls */
84 hb_face_collect_variation_unicodes (face, cp, set);
85
86 hb_codepoint_t g;
87 hb_font_get_nominal_glyph (font, cp, &g);
88 hb_font_get_variation_glyph (font, cp, cp, &g);
89 hb_font_get_glyph_h_advance (font, cp);
90 hb_font_get_glyph_v_advance (font, cp);
91 hb_position_t x, y;
92 hb_font_get_glyph_h_origin (font, cp, &x, &y);
93 hb_font_get_glyph_v_origin (font, cp, &x, &y);
94 hb_font_get_glyph_contour_point (font, cp, 0, &x, &y);
95 char buf[64];
96 hb_font_get_glyph_name (font, cp, buf, sizeof (buf));
97
98 hb_ot_color_palette_get_name_id (face, cp);
99 hb_ot_color_palette_color_get_name_id (face, cp);
100 hb_ot_color_palette_get_flags (face, cp);
101 hb_ot_color_palette_get_colors (face, cp, 0, nullptr, nullptr);
102 hb_ot_color_glyph_get_layers (face, cp, 0, nullptr, nullptr);
103 hb_blob_destroy (hb_ot_color_glyph_reference_svg (face, cp));
104 hb_blob_destroy (hb_ot_color_glyph_reference_png (font, cp));
105
106 hb_ot_layout_get_ligature_carets (font, HB_DIRECTION_LTR, cp, 0, nullptr, nullptr);
107
108 hb_ot_math_get_glyph_italics_correction (font, cp);
109 hb_ot_math_get_glyph_top_accent_attachment (font, cp);
110 hb_ot_math_is_glyph_extended_shape (face, cp);
111 hb_ot_math_get_glyph_kerning (font, cp, HB_OT_MATH_KERN_BOTTOM_RIGHT, 0);
112 hb_ot_math_get_glyph_variants (font, cp, HB_DIRECTION_TTB, 0, nullptr, nullptr);
113 hb_ot_math_get_glyph_assembly (font, cp, HB_DIRECTION_BTT, 0, nullptr, nullptr, nullptr);
114 }
115
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)116 extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
117 {
118 alloc_state = size; /* see src/failing-alloc.c */
119
120 hb_blob_t *blob = hb_blob_create ((const char *) data, size,
121 HB_MEMORY_MODE_READONLY, nullptr, nullptr);
122 hb_face_t *face = hb_face_create (blob, 0);
123 hb_font_t *font = hb_font_create (face);
124
125 unsigned num_coords = 0;
126 if (size) num_coords = data[size - 1];
127 num_coords = hb_ot_var_get_axis_count (face) > num_coords ? num_coords : hb_ot_var_get_axis_count (face);
128 int *coords = (int *) calloc (num_coords, sizeof (int));
129 if (size > num_coords + 1)
130 for (unsigned i = 0; i < num_coords; ++i)
131 coords[i] = ((int) data[size - num_coords + i - 1] - 128) * 10;
132 hb_font_set_var_coords_normalized (font, coords, num_coords);
133 free (coords);
134
135 unsigned glyph_count = hb_face_get_glyph_count (face);
136 glyph_count = glyph_count > 16 ? 16 : glyph_count;
137
138 #ifdef HB_EXPERIMENTAL_API
139 _user_data_t user_data = {false, 0, 0, 0, 0, 0};
140
141 hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
142 hb_draw_funcs_set_move_to_func (funcs, (hb_draw_move_to_func_t) _move_to);
143 hb_draw_funcs_set_line_to_func (funcs, (hb_draw_line_to_func_t) _line_to);
144 hb_draw_funcs_set_quadratic_to_func (funcs, (hb_draw_quadratic_to_func_t) _quadratic_to);
145 hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) _cubic_to);
146 hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) _close_path);
147 #endif
148 volatile unsigned counter = !glyph_count;
149 hb_set_t *set = hb_set_create ();
150 for (unsigned gid = 0; gid < glyph_count; ++gid)
151 {
152 #ifdef HB_EXPERIMENTAL_API
153 hb_font_draw_glyph (font, gid, funcs, &user_data);
154 assert (!user_data.is_open);
155 #endif
156
157 /* Glyph extents also may practices the similar path, call it now that is related */
158 hb_glyph_extents_t extents;
159 if (hb_font_get_glyph_extents (font, gid, &extents))
160 counter += !!extents.width + !!extents.height + !!extents.x_bearing + !!extents.y_bearing;
161
162 if (!counter) counter += 1;
163
164 /* other misc calls */
165 misc_calls_for_gid (face, font, set, gid);
166 }
167 hb_set_destroy (set);
168 assert (counter);
169 #ifdef HB_EXPERIMENTAL_API
170 hb_draw_funcs_destroy (funcs);
171 #endif
172
173 hb_font_destroy (font);
174 hb_face_destroy (face);
175 hb_blob_destroy (blob);
176 return 0;
177 }
178