diff --git a/src/graph/gsubgpos-graph.hh b/src/graph/gsubgpos-graph.hh index 937e05876..f7dcc4bfd 100644 --- a/src/graph/gsubgpos-graph.hh +++ b/src/graph/gsubgpos-graph.hh @@ -47,6 +47,12 @@ struct ExtensionFormat1 : public OT::ExtensionFormat1 this->extensionOffset = 0; } + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + return vertex_len >= OT::ExtensionFormat1::static_size; + } + unsigned get_lookup_type () const { return this->extensionLookupType; @@ -118,7 +124,6 @@ struct Lookup : public OT::Lookup if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair) return true; - // TODO check subtable type. hb_vector_t all_new_subtables; for (unsigned i = 0; i < subTable.len; i++) { @@ -128,6 +133,8 @@ struct Lookup : public OT::Lookup ExtensionFormat1* extension = (ExtensionFormat1*) c.graph.object (ext_subtable_index).head; + if (!extension->sanitize (c.graph.vertices_[ext_subtable_index])) + continue; subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index); type = extension->get_lookup_type (); @@ -136,7 +143,8 @@ struct Lookup : public OT::Lookup } PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head; - // TODO sanitize + if (!pairPos->sanitize (c.graph.vertices_[subtable_index])) continue; + hb_vector_t new_sub_tables = pairPos->split_subtables (c, subtable_index); if (new_sub_tables.in_error ()) return false; + new_sub_tables.iter() | hb_sink (all_new_subtables); diff --git a/src/graph/pairpos-graph.hh b/src/graph/pairpos-graph.hh index 777867c0a..2b0183d64 100644 --- a/src/graph/pairpos-graph.hh +++ b/src/graph/pairpos-graph.hh @@ -34,6 +34,16 @@ namespace graph { struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3 { + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3::min_size; + if (vertex_len < min_size) return false; + + return vertex_len >= + min_size + pairSet.get_size () - pairSet.len.get_size(); + } + hb_vector_t split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) { hb_set_t visited; @@ -218,6 +228,12 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3 { + bool sanitize (graph_t::vertex_t& vertex) const + { + // TODO + return true; + } + hb_vector_t split_subtables (gsubgpos_graph_context_t& c, unsigned this_index) { // TODO @@ -243,6 +259,24 @@ struct PairPos : public OT::Layout::GPOS_impl::PairPos return hb_vector_t (); } } + + bool sanitize (graph_t::vertex_t& vertex) const + { + int64_t vertex_len = vertex.obj.tail - vertex.obj.head; + if (vertex_len < u.format.get_size ()) return false; + + switch (u.format) { + case 1: + return ((PairPosFormat1*)(&u.format1))->sanitize (vertex); + case 2: + return ((PairPosFormat2*)(&u.format2))->sanitize (vertex); + case 3: + case 4: + default: + // We don't handle format 3 and 4 here. + return false; + } + } }; }