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-repacker.h"
9*2d1272b8SAndroid Build Coastguard Worker
10*2d1272b8SAndroid Build Coastguard Worker typedef struct
11*2d1272b8SAndroid Build Coastguard Worker {
12*2d1272b8SAndroid Build Coastguard Worker uint16_t parent;
13*2d1272b8SAndroid Build Coastguard Worker uint16_t child;
14*2d1272b8SAndroid Build Coastguard Worker uint16_t position;
15*2d1272b8SAndroid Build Coastguard Worker uint8_t width;
16*2d1272b8SAndroid Build Coastguard Worker } link_t;
17*2d1272b8SAndroid Build Coastguard Worker
18*2d1272b8SAndroid Build Coastguard Worker /* The fuzzer seed contains a serialized representation of a object graph which forms
19*2d1272b8SAndroid Build Coastguard Worker * the input graph to the repacker call. The binary format is:
20*2d1272b8SAndroid Build Coastguard Worker *
21*2d1272b8SAndroid Build Coastguard Worker * table tag: 4 bytes
22*2d1272b8SAndroid Build Coastguard Worker * number of objects: 2 bytes
23*2d1272b8SAndroid Build Coastguard Worker * objects[number of objects]:
24*2d1272b8SAndroid Build Coastguard Worker * blob size: 2 bytes
25*2d1272b8SAndroid Build Coastguard Worker * blob: blob size bytes
26*2d1272b8SAndroid Build Coastguard Worker * num of real links: 2 bytes
27*2d1272b8SAndroid Build Coastguard Worker * links[number of real links]: link_t struct
28*2d1272b8SAndroid Build Coastguard Worker *
29*2d1272b8SAndroid Build Coastguard Worker * TODO(garretrieger): add optional virtual links
30*2d1272b8SAndroid Build Coastguard Worker */
31*2d1272b8SAndroid Build Coastguard Worker
32*2d1272b8SAndroid Build Coastguard Worker template <typename T>
read(const uint8_t ** data,size_t * size,T * out)33*2d1272b8SAndroid Build Coastguard Worker bool read(const uint8_t** data, size_t* size, T* out)
34*2d1272b8SAndroid Build Coastguard Worker {
35*2d1272b8SAndroid Build Coastguard Worker if (*size < sizeof (T)) return false;
36*2d1272b8SAndroid Build Coastguard Worker
37*2d1272b8SAndroid Build Coastguard Worker memcpy(out, *data, sizeof (T));
38*2d1272b8SAndroid Build Coastguard Worker
39*2d1272b8SAndroid Build Coastguard Worker *data += sizeof (T);
40*2d1272b8SAndroid Build Coastguard Worker *size -= sizeof (T);
41*2d1272b8SAndroid Build Coastguard Worker
42*2d1272b8SAndroid Build Coastguard Worker return true;
43*2d1272b8SAndroid Build Coastguard Worker }
44*2d1272b8SAndroid Build Coastguard Worker
cleanup(hb_object_t * objects,uint16_t num_objects)45*2d1272b8SAndroid Build Coastguard Worker void cleanup (hb_object_t* objects, uint16_t num_objects)
46*2d1272b8SAndroid Build Coastguard Worker {
47*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_objects; i++)
48*2d1272b8SAndroid Build Coastguard Worker {
49*2d1272b8SAndroid Build Coastguard Worker free (objects[i].head);
50*2d1272b8SAndroid Build Coastguard Worker free (objects[i].real_links);
51*2d1272b8SAndroid Build Coastguard Worker }
52*2d1272b8SAndroid Build Coastguard Worker }
53*2d1272b8SAndroid Build Coastguard Worker
add_links_to_objects(hb_object_t * objects,uint16_t num_objects,link_t * links,uint16_t num_links)54*2d1272b8SAndroid Build Coastguard Worker void add_links_to_objects (hb_object_t* objects, uint16_t num_objects,
55*2d1272b8SAndroid Build Coastguard Worker link_t* links, uint16_t num_links)
56*2d1272b8SAndroid Build Coastguard Worker {
57*2d1272b8SAndroid Build Coastguard Worker unsigned* link_count = (unsigned*) calloc (num_objects, sizeof (unsigned));
58*2d1272b8SAndroid Build Coastguard Worker
59*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_links; i++)
60*2d1272b8SAndroid Build Coastguard Worker {
61*2d1272b8SAndroid Build Coastguard Worker uint16_t parent_idx = links[i].parent;
62*2d1272b8SAndroid Build Coastguard Worker link_count[parent_idx]++;
63*2d1272b8SAndroid Build Coastguard Worker }
64*2d1272b8SAndroid Build Coastguard Worker
65*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_objects; i++)
66*2d1272b8SAndroid Build Coastguard Worker {
67*2d1272b8SAndroid Build Coastguard Worker objects[i].num_real_links = link_count[i];
68*2d1272b8SAndroid Build Coastguard Worker objects[i].real_links = (hb_link_t*) calloc (link_count[i], sizeof (hb_link_t));
69*2d1272b8SAndroid Build Coastguard Worker objects[i].num_virtual_links = 0;
70*2d1272b8SAndroid Build Coastguard Worker objects[i].virtual_links = nullptr;
71*2d1272b8SAndroid Build Coastguard Worker }
72*2d1272b8SAndroid Build Coastguard Worker
73*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_links; i++)
74*2d1272b8SAndroid Build Coastguard Worker {
75*2d1272b8SAndroid Build Coastguard Worker uint16_t parent_idx = links[i].parent;
76*2d1272b8SAndroid Build Coastguard Worker uint16_t child_idx = links[i].child + 1; // All indices are shifted by 1 by the null object.
77*2d1272b8SAndroid Build Coastguard Worker hb_link_t* link = &(objects[parent_idx].real_links[link_count[parent_idx] - 1]);
78*2d1272b8SAndroid Build Coastguard Worker
79*2d1272b8SAndroid Build Coastguard Worker link->width = links[i].width;
80*2d1272b8SAndroid Build Coastguard Worker link->position = links[i].position;
81*2d1272b8SAndroid Build Coastguard Worker link->objidx = child_idx;
82*2d1272b8SAndroid Build Coastguard Worker link_count[parent_idx]--;
83*2d1272b8SAndroid Build Coastguard Worker }
84*2d1272b8SAndroid Build Coastguard Worker
85*2d1272b8SAndroid Build Coastguard Worker free (link_count);
86*2d1272b8SAndroid Build Coastguard Worker }
87*2d1272b8SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)88*2d1272b8SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
89*2d1272b8SAndroid Build Coastguard Worker {
90*2d1272b8SAndroid Build Coastguard Worker // TODO(garretrieger): move graph validity checks into repacker graph creation.
91*2d1272b8SAndroid Build Coastguard Worker alloc_state = _fuzzing_alloc_state (data, size);
92*2d1272b8SAndroid Build Coastguard Worker
93*2d1272b8SAndroid Build Coastguard Worker uint16_t num_objects = 0;
94*2d1272b8SAndroid Build Coastguard Worker hb_object_t* objects = nullptr;
95*2d1272b8SAndroid Build Coastguard Worker
96*2d1272b8SAndroid Build Coastguard Worker uint16_t num_real_links = 0;
97*2d1272b8SAndroid Build Coastguard Worker link_t* links = nullptr;
98*2d1272b8SAndroid Build Coastguard Worker
99*2d1272b8SAndroid Build Coastguard Worker hb_tag_t table_tag;
100*2d1272b8SAndroid Build Coastguard Worker if (!read<hb_tag_t> (&data, &size, &table_tag)) goto end;
101*2d1272b8SAndroid Build Coastguard Worker if (!read<uint16_t> (&data, &size, &num_objects)) goto end;
102*2d1272b8SAndroid Build Coastguard Worker
103*2d1272b8SAndroid Build Coastguard Worker objects = (hb_object_t*) calloc (num_objects, sizeof (hb_object_t));
104*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_objects; i++)
105*2d1272b8SAndroid Build Coastguard Worker {
106*2d1272b8SAndroid Build Coastguard Worker uint16_t blob_size;
107*2d1272b8SAndroid Build Coastguard Worker if (!read<uint16_t> (&data, &size, &blob_size)) goto end;
108*2d1272b8SAndroid Build Coastguard Worker if (size < blob_size) goto end;
109*2d1272b8SAndroid Build Coastguard Worker
110*2d1272b8SAndroid Build Coastguard Worker char* copy = (char*) calloc (1, blob_size);
111*2d1272b8SAndroid Build Coastguard Worker memcpy (copy, data, blob_size);
112*2d1272b8SAndroid Build Coastguard Worker objects[i].head = (char*) copy;
113*2d1272b8SAndroid Build Coastguard Worker objects[i].tail = (char*) (copy + blob_size);
114*2d1272b8SAndroid Build Coastguard Worker
115*2d1272b8SAndroid Build Coastguard Worker size -= blob_size;
116*2d1272b8SAndroid Build Coastguard Worker data += blob_size;
117*2d1272b8SAndroid Build Coastguard Worker }
118*2d1272b8SAndroid Build Coastguard Worker
119*2d1272b8SAndroid Build Coastguard Worker if (!read<uint16_t> (&data, &size, &num_real_links)) goto end;
120*2d1272b8SAndroid Build Coastguard Worker links = (link_t*) calloc (num_real_links, sizeof (link_t));
121*2d1272b8SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_real_links; i++)
122*2d1272b8SAndroid Build Coastguard Worker {
123*2d1272b8SAndroid Build Coastguard Worker if (!read<link_t> (&data, &size, &links[i])) goto end;
124*2d1272b8SAndroid Build Coastguard Worker
125*2d1272b8SAndroid Build Coastguard Worker if (links[i].parent >= num_objects)
126*2d1272b8SAndroid Build Coastguard Worker goto end;
127*2d1272b8SAndroid Build Coastguard Worker }
128*2d1272b8SAndroid Build Coastguard Worker
129*2d1272b8SAndroid Build Coastguard Worker add_links_to_objects (objects, num_objects,
130*2d1272b8SAndroid Build Coastguard Worker links, num_real_links);
131*2d1272b8SAndroid Build Coastguard Worker
132*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (hb_subset_repack_or_fail (table_tag,
133*2d1272b8SAndroid Build Coastguard Worker objects,
134*2d1272b8SAndroid Build Coastguard Worker num_objects));
135*2d1272b8SAndroid Build Coastguard Worker
136*2d1272b8SAndroid Build Coastguard Worker end:
137*2d1272b8SAndroid Build Coastguard Worker if (objects)
138*2d1272b8SAndroid Build Coastguard Worker {
139*2d1272b8SAndroid Build Coastguard Worker cleanup (objects, num_objects);
140*2d1272b8SAndroid Build Coastguard Worker free (objects);
141*2d1272b8SAndroid Build Coastguard Worker }
142*2d1272b8SAndroid Build Coastguard Worker free (links);
143*2d1272b8SAndroid Build Coastguard Worker
144*2d1272b8SAndroid Build Coastguard Worker return 0;
145*2d1272b8SAndroid Build Coastguard Worker }
146