[repacker] Validate link positions before running the repacker.
diff --git a/src/graph/graph.hh b/src/graph/graph.hh
index b81f869..8a947ab 100644
--- a/src/graph/graph.hh
+++ b/src/graph/graph.hh
@@ -49,6 +49,34 @@
unsigned end = 0;
unsigned priority = 0;
+
+ bool link_positions_valid (unsigned parent_index)
+ {
+ hb_set_t assigned_bytes;
+ for (const auto& l : obj.real_links)
+ {
+ unsigned start = l.position;
+ unsigned end = start + l.width - 1;
+
+ if (unlikely (end >= table_size ()))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Link position is out of bounds.");
+ return false;
+ }
+
+ if (unlikely (assigned_bytes.intersects (start, end)))
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Invalid graph. Found offsets whose positions overlap.");
+ return false;
+ }
+
+ assigned_bytes.add_range (start, end);
+ }
+ return true;
+ }
+
void normalize ()
{
obj.real_links.qsort ();
@@ -299,6 +327,8 @@
vertex_t* v = vertices_.push ();
if (check_success (!vertices_.in_error ()))
v->obj = *objects[i];
+
+ check_success (v->link_positions_valid (i));
if (!removed_nil) continue;
// Fix indices to account for removed nil object.
for (auto& l : v->obj.all_links_writer ()) {
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index f6ee403..1abb957 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -376,6 +376,12 @@
unsigned max_rounds = 20,
bool recalculate_extensions = false) {
graph_t sorted_graph (packed);
+ if (sorted_graph.in_error ())
+ {
+ // Invalid graph definition.
+ return nullptr;
+ }
+
if (!sorted_graph.is_fully_connected ())
{
sorted_graph.print_orphaned_nodes ();
diff --git a/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774 b/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774
new file mode 100644
index 0000000..0160ce5
--- /dev/null
+++ b/test/fuzzing/graphs/crash-442bfac994a3d9929cf06262ae9fb00f6ee1f774
Binary files differ
diff --git a/test/fuzzing/hb-repacker-fuzzer.cc b/test/fuzzing/hb-repacker-fuzzer.cc
index fb73df6..837f415 100644
--- a/test/fuzzing/hb-repacker-fuzzer.cc
+++ b/test/fuzzing/hb-repacker-fuzzer.cc
@@ -73,6 +73,7 @@
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;