[repacker] begin implementing a fuzzer for the repacker api.
This commit is contained in:
parent
2658370f00
commit
985b19f678
|
@ -941,6 +941,18 @@ struct graph_t
|
|||
return made_change;
|
||||
}
|
||||
|
||||
bool is_fully_connected ()
|
||||
{
|
||||
update_parents();
|
||||
|
||||
for (unsigned i = 0; i < root_idx (); i++)
|
||||
{
|
||||
if (!vertices_[i].parents)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void print_orphaned_nodes ()
|
||||
{
|
||||
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
|
||||
|
|
|
@ -376,6 +376,12 @@ hb_resolve_overflows (const T& packed,
|
|||
unsigned max_rounds = 20,
|
||||
bool recalculate_extensions = false) {
|
||||
graph_t sorted_graph (packed);
|
||||
if (!sorted_graph.is_fully_connected ())
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Input graph is not fully connected.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!hb_resolve_graph_overflows (table_tag, max_rounds, recalculate_extensions, sorted_graph))
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
#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 delta;
|
||||
uint16_t position;
|
||||
uint8_t width;
|
||||
} link_t;
|
||||
|
||||
template <typename T>
|
||||
bool read(const uint8_t** data, size_t* size, T* out)
|
||||
{
|
||||
if (*size < sizeof (T)) return false;
|
||||
|
||||
*out = * ((T*) *data);
|
||||
|
||||
*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].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].parent + links[i].delta + 1;
|
||||
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]--;
|
||||
}
|
||||
|
||||
bool* reachable = (bool*) calloc (num_objects, sizeof (bool));
|
||||
|
||||
|
||||
|
||||
free (reachable);
|
||||
free (link_count);
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||
{
|
||||
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;
|
||||
|
||||
objects[i].head = (char*) data;
|
||||
objects[i].tail = (char*) (data + 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;
|
||||
|
||||
uint32_t child_idx = ((uint32_t) links[i].parent) + ((uint32_t) links[i].delta) + 1;
|
||||
if (links[i].parent >= num_objects
|
||||
|| child_idx >= num_objects)
|
||||
goto end;
|
||||
|
||||
if (links[i].width < 2 || links[i].width > 4) 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;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
tests = [
|
||||
'hb-shape-fuzzer.cc',
|
||||
'hb-subset-fuzzer.cc',
|
||||
'hb-repacker-fuzzer.cc',
|
||||
'hb-set-fuzzer.cc',
|
||||
'hb-draw-fuzzer.cc',
|
||||
]
|
||||
|
@ -19,6 +20,8 @@ foreach file_name : tests
|
|||
extra_cpp_args += '-DHB_IS_IN_FUZZER'
|
||||
endif
|
||||
|
||||
# TODO tie this to the experimental api setting.
|
||||
extra_cpp_args += '-DHB_EXPERIMENTAL_API'
|
||||
exe = executable(test_name, sources,
|
||||
cpp_args: cpp_args + extra_cpp_args,
|
||||
include_directories: [incconfig, incsrc],
|
||||
|
|
Loading…
Reference in New Issue