xref: /aosp_15_r20/external/harfbuzz_ng/test/fuzzing/hb-subset-fuzzer.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #include "hb-fuzzer.hh"
2*2d1272b8SAndroid Build Coastguard Worker 
3*2d1272b8SAndroid Build Coastguard Worker #include <stdlib.h>
4*2d1272b8SAndroid Build Coastguard Worker #include <stdio.h>
5*2d1272b8SAndroid Build Coastguard Worker #include <string.h>
6*2d1272b8SAndroid Build Coastguard Worker #include <assert.h>
7*2d1272b8SAndroid Build Coastguard Worker 
8*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset.h"
9*2d1272b8SAndroid Build Coastguard Worker 
10*2d1272b8SAndroid Build Coastguard Worker static void
trySubset(hb_face_t * face,const hb_codepoint_t text[],int text_length,unsigned flag_bits,hb_subset_input_t * input)11*2d1272b8SAndroid Build Coastguard Worker trySubset (hb_face_t *face,
12*2d1272b8SAndroid Build Coastguard Worker 	   const hb_codepoint_t text[],
13*2d1272b8SAndroid Build Coastguard Worker 	   int text_length,
14*2d1272b8SAndroid Build Coastguard Worker            unsigned flag_bits,
15*2d1272b8SAndroid Build Coastguard Worker            hb_subset_input_t *input)
16*2d1272b8SAndroid Build Coastguard Worker {
17*2d1272b8SAndroid Build Coastguard Worker   if (!input) return;
18*2d1272b8SAndroid Build Coastguard Worker 
19*2d1272b8SAndroid Build Coastguard Worker   hb_subset_input_set_flags (input, (hb_subset_flags_t) flag_bits);
20*2d1272b8SAndroid Build Coastguard Worker 
21*2d1272b8SAndroid Build Coastguard Worker   hb_set_t *codepoints = hb_subset_input_unicode_set (input);
22*2d1272b8SAndroid Build Coastguard Worker 
23*2d1272b8SAndroid Build Coastguard Worker   for (int i = 0; i < text_length; i++)
24*2d1272b8SAndroid Build Coastguard Worker     hb_set_add (codepoints, text[i]);
25*2d1272b8SAndroid Build Coastguard Worker 
26*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *result = hb_subset_or_fail (face, input);
27*2d1272b8SAndroid Build Coastguard Worker   if (result)
28*2d1272b8SAndroid Build Coastguard Worker   {
29*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *blob = hb_face_reference_blob (result);
30*2d1272b8SAndroid Build Coastguard Worker     unsigned int length;
31*2d1272b8SAndroid Build Coastguard Worker     const char *data = hb_blob_get_data (blob, &length);
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker     // Something not optimizable just to access all the blob data
34*2d1272b8SAndroid Build Coastguard Worker     unsigned int bytes_count = 0;
35*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < length; ++i)
36*2d1272b8SAndroid Build Coastguard Worker       if (data[i]) ++bytes_count;
37*2d1272b8SAndroid Build Coastguard Worker     assert (bytes_count || !length);
38*2d1272b8SAndroid Build Coastguard Worker 
39*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (blob);
40*2d1272b8SAndroid Build Coastguard Worker   }
41*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (result);
42*2d1272b8SAndroid Build Coastguard Worker 
43*2d1272b8SAndroid Build Coastguard Worker   hb_subset_input_destroy (input);
44*2d1272b8SAndroid Build Coastguard Worker }
45*2d1272b8SAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)46*2d1272b8SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
47*2d1272b8SAndroid Build Coastguard Worker {
48*2d1272b8SAndroid Build Coastguard Worker   alloc_state = _fuzzing_alloc_state (data, size);
49*2d1272b8SAndroid Build Coastguard Worker 
50*2d1272b8SAndroid Build Coastguard Worker   hb_blob_t *blob = hb_blob_create ((const char *) data, size,
51*2d1272b8SAndroid Build Coastguard Worker 				    HB_MEMORY_MODE_READONLY, nullptr, nullptr);
52*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face = hb_face_create (blob, 0);
53*2d1272b8SAndroid Build Coastguard Worker 
54*2d1272b8SAndroid Build Coastguard Worker   /* Just test this API here quickly. */
55*2d1272b8SAndroid Build Coastguard Worker   hb_set_t *output = hb_set_create ();
56*2d1272b8SAndroid Build Coastguard Worker   hb_face_collect_unicodes (face, output);
57*2d1272b8SAndroid Build Coastguard Worker   hb_set_destroy (output);
58*2d1272b8SAndroid Build Coastguard Worker 
59*2d1272b8SAndroid Build Coastguard Worker   unsigned flags = HB_SUBSET_FLAGS_DEFAULT;
60*2d1272b8SAndroid Build Coastguard Worker   const hb_codepoint_t text[] =
61*2d1272b8SAndroid Build Coastguard Worker       {
62*2d1272b8SAndroid Build Coastguard Worker 	'A', 'B', 'C', 'D', 'E', 'X', 'Y', 'Z', '1', '2',
63*2d1272b8SAndroid Build Coastguard Worker 	'3', '@', '_', '%', '&', ')', '*', '$', '!'
64*2d1272b8SAndroid Build Coastguard Worker       };
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
67*2d1272b8SAndroid Build Coastguard Worker   if (!input)
68*2d1272b8SAndroid Build Coastguard Worker   {
69*2d1272b8SAndroid Build Coastguard Worker     hb_face_destroy (face);
70*2d1272b8SAndroid Build Coastguard Worker     hb_blob_destroy (blob);
71*2d1272b8SAndroid Build Coastguard Worker     return 0;
72*2d1272b8SAndroid Build Coastguard Worker   }
73*2d1272b8SAndroid Build Coastguard Worker   trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), flags, input);
74*2d1272b8SAndroid Build Coastguard Worker 
75*2d1272b8SAndroid Build Coastguard Worker   unsigned num_axes;
76*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t text_from_data[16];
77*2d1272b8SAndroid Build Coastguard Worker   if (size > sizeof (text_from_data) + sizeof (flags) + sizeof(num_axes)) {
78*2d1272b8SAndroid Build Coastguard Worker     hb_subset_input_t *input = hb_subset_input_create_or_fail ();
79*2d1272b8SAndroid Build Coastguard Worker     if (!input)
80*2d1272b8SAndroid Build Coastguard Worker     {
81*2d1272b8SAndroid Build Coastguard Worker       hb_face_destroy (face);
82*2d1272b8SAndroid Build Coastguard Worker       hb_blob_destroy (blob);
83*2d1272b8SAndroid Build Coastguard Worker       return 0;
84*2d1272b8SAndroid Build Coastguard Worker     }
85*2d1272b8SAndroid Build Coastguard Worker     size -= sizeof (text_from_data);
86*2d1272b8SAndroid Build Coastguard Worker     memcpy (text_from_data,
87*2d1272b8SAndroid Build Coastguard Worker 	    data + size,
88*2d1272b8SAndroid Build Coastguard Worker 	    sizeof (text_from_data));
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker     size -= sizeof (flags);
91*2d1272b8SAndroid Build Coastguard Worker     memcpy (&flags,
92*2d1272b8SAndroid Build Coastguard Worker 	    data + size,
93*2d1272b8SAndroid Build Coastguard Worker 	    sizeof (flags));
94*2d1272b8SAndroid Build Coastguard Worker 
95*2d1272b8SAndroid Build Coastguard Worker     size -= sizeof (num_axes);
96*2d1272b8SAndroid Build Coastguard Worker     memcpy (&num_axes,
97*2d1272b8SAndroid Build Coastguard Worker 	    data + size,
98*2d1272b8SAndroid Build Coastguard Worker 	    sizeof (num_axes));
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker     if (num_axes > 0 && num_axes < 8 && size > num_axes * (sizeof(hb_tag_t) + sizeof(int)))
101*2d1272b8SAndroid Build Coastguard Worker     {
102*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_axes; i++) {
103*2d1272b8SAndroid Build Coastguard Worker         hb_tag_t tag;
104*2d1272b8SAndroid Build Coastguard Worker         int value;
105*2d1272b8SAndroid Build Coastguard Worker         size -= sizeof (tag);
106*2d1272b8SAndroid Build Coastguard Worker         memcpy (&tag,
107*2d1272b8SAndroid Build Coastguard Worker                 data + size,
108*2d1272b8SAndroid Build Coastguard Worker                 sizeof (tag));
109*2d1272b8SAndroid Build Coastguard Worker         size -= sizeof (value);
110*2d1272b8SAndroid Build Coastguard Worker         memcpy (&value,
111*2d1272b8SAndroid Build Coastguard Worker                 data + size,
112*2d1272b8SAndroid Build Coastguard Worker                 sizeof (value));
113*2d1272b8SAndroid Build Coastguard Worker 
114*2d1272b8SAndroid Build Coastguard Worker         hb_subset_input_pin_axis_location(input,
115*2d1272b8SAndroid Build Coastguard Worker                                           face,
116*2d1272b8SAndroid Build Coastguard Worker                                           tag,
117*2d1272b8SAndroid Build Coastguard Worker                                           (float) value);
118*2d1272b8SAndroid Build Coastguard Worker       }
119*2d1272b8SAndroid Build Coastguard Worker     }
120*2d1272b8SAndroid Build Coastguard Worker 
121*2d1272b8SAndroid Build Coastguard Worker 
122*2d1272b8SAndroid Build Coastguard Worker 
123*2d1272b8SAndroid Build Coastguard Worker     unsigned int text_size = sizeof (text_from_data) / sizeof (hb_codepoint_t);
124*2d1272b8SAndroid Build Coastguard Worker     trySubset (face, text_from_data, text_size, flags, input);
125*2d1272b8SAndroid Build Coastguard Worker   }
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
128*2d1272b8SAndroid Build Coastguard Worker   hb_blob_destroy (blob);
129*2d1272b8SAndroid Build Coastguard Worker 
130*2d1272b8SAndroid Build Coastguard Worker   return 0;
131*2d1272b8SAndroid Build Coastguard Worker }
132