| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- #include "hb-fuzzer.hh"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #include "hb-subset-repacker.h"
- typedef struct
- {
- uint16_t parent;
- uint16_t child;
- uint16_t position;
- uint8_t width;
- } link_t;
- /* The fuzzer seed contains a serialized representation of a object graph which forms
- * the input graph to the repacker call. The binary format is:
- *
- * table tag: 4 bytes
- * number of objects: 2 bytes
- * objects[number of objects]:
- * blob size: 2 bytes
- * blob: blob size bytes
- * num of real links: 2 bytes
- * links[number of real links]: link_t struct
- *
- * TODO(garretrieger): add optional virtual links
- */
- template <typename T>
- bool read(const uint8_t** data, size_t* size, T* out)
- {
- if (*size < sizeof (T)) return false;
- memcpy(out, *data, sizeof (T));
- *data += sizeof (T);
- *size -= sizeof (T);
- return true;
- }
- void cleanup (hb_object_t* objects, uint16_t num_objects)
- {
- for (uint32_t i = 0; i < num_objects; i++)
- {
- free (objects[i].head);
- free (objects[i].real_links);
- }
- }
- void add_links_to_objects (hb_object_t* objects, uint16_t num_objects,
- link_t* links, uint16_t num_links)
- {
- unsigned* link_count = (unsigned*) calloc (num_objects, sizeof (unsigned));
- for (uint32_t i = 0; i < num_links; i++)
- {
- uint16_t parent_idx = links[i].parent;
- link_count[parent_idx]++;
- }
- for (uint32_t i = 0; i < num_objects; i++)
- {
- objects[i].num_real_links = link_count[i];
- objects[i].real_links = (hb_link_t*) calloc (link_count[i], sizeof (hb_link_t));
- objects[i].num_virtual_links = 0;
- objects[i].virtual_links = nullptr;
- }
- for (uint32_t i = 0; i < num_links; i++)
- {
- uint16_t parent_idx = links[i].parent;
- uint16_t child_idx = links[i].child + 1; // All indices are shifted by 1 by the null object.
- hb_link_t* link = &(objects[parent_idx].real_links[link_count[parent_idx] - 1]);
- link->width = links[i].width;
- link->position = links[i].position;
- link->objidx = child_idx;
- link_count[parent_idx]--;
- }
- free (link_count);
- }
- extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
- {
- // TODO(garretrieger): move graph validity checks into repacker graph creation.
- alloc_state = _fuzzing_alloc_state (data, size);
- uint16_t num_objects = 0;
- hb_object_t* objects = nullptr;
- uint16_t num_real_links = 0;
- link_t* links = nullptr;
- hb_tag_t table_tag;
- if (!read<hb_tag_t> (&data, &size, &table_tag)) goto end;
- if (!read<uint16_t> (&data, &size, &num_objects)) goto end;
- objects = (hb_object_t*) calloc (num_objects, sizeof (hb_object_t));
- for (uint32_t i = 0; i < num_objects; i++)
- {
- uint16_t blob_size;
- if (!read<uint16_t> (&data, &size, &blob_size)) goto end;
- if (size < blob_size) goto end;
- char* copy = (char*) calloc (1, blob_size);
- memcpy (copy, data, blob_size);
- objects[i].head = (char*) copy;
- objects[i].tail = (char*) (copy + blob_size);
- size -= blob_size;
- data += blob_size;
- }
- if (!read<uint16_t> (&data, &size, &num_real_links)) goto end;
- links = (link_t*) calloc (num_real_links, sizeof (link_t));
- for (uint32_t i = 0; i < num_real_links; i++)
- {
- if (!read<link_t> (&data, &size, &links[i])) goto end;
- if (links[i].parent >= num_objects)
- goto end;
- }
- add_links_to_objects (objects, num_objects,
- links, num_real_links);
- hb_blob_destroy (hb_subset_repack_or_fail (table_tag,
- objects,
- num_objects));
- end:
- if (objects)
- {
- cleanup (objects, num_objects);
- free (objects);
- }
- free (links);
- return 0;
- }
|