[subset] hook up the repacker to run if offset overflows are encountered during subsetting.

This commit is contained in:
Garret Rieger 2020-10-30 12:16:26 -07:00
parent f4c78cc7dd
commit 6b1ea4cbe7
2 changed files with 40 additions and 3 deletions

View File

@ -136,7 +136,14 @@ struct hb_serialize_context_t
template <typename T1, typename T2>
bool check_equal (T1 &&v1, T2 &&v2)
{ return check_success ((long long) v1 == (long long) v2); }
{
if ((long long) v1 != (long long) v2)
{
err_offset_overflow ();
return false;
}
return true;
}
template <typename T1, typename T2>
bool check_assign (T1 &v1, T2 &&v2)
@ -400,6 +407,7 @@ struct hb_serialize_context_t
/* Following two functions exist to allow setting breakpoint on. */
void err_ran_out_of_room () { this->ran_out_of_room = true; }
void err_offset_overflow () { this->offset_overflow = true; }
void err_other_error () { this->successful = false; }
template <typename Type>
@ -520,7 +528,7 @@ struct hb_serialize_context_t
(char *) b.arrayZ, free);
}
const hb_vector_t<object_t *>& object_graph()
const hb_vector_t<object_t *>& object_graph() const
{ return packed; }
private:
@ -537,6 +545,7 @@ struct hb_serialize_context_t
unsigned int debug_depth;
bool successful;
bool ran_out_of_room;
bool offset_overflow;
private:

View File

@ -50,6 +50,7 @@
#include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-repacker.hh"
static unsigned
@ -64,6 +65,32 @@ _plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
}
/*
* Repack the serialization buffer if any offset overflows exist.
*/
static hb_blob_t*
_repack (const hb_serialize_context_t& c)
{
if (!c.offset_overflow)
return c.copy_blob ();
hb_vector_t<char> buf;
int buf_size = c.end - c.start;
if (unlikely (!buf.alloc (buf_size)))
return nullptr;
hb_serialize_context_t repacked ((void *) buf, buf_size);
hb_resolve_overflows (c.object_graph (), &repacked);
if (unlikely (repacked.ran_out_of_room || repacked.in_error () || repacked.offset_overflow))
// TODO(garretrieger): refactor so we can share the resize/retry logic with the subset
// portion.
return nullptr;
return repacked.copy_blob ();
}
template<typename TableType>
static bool
_subset (hb_subset_plan_t *plan)
@ -111,7 +138,8 @@ _subset (hb_subset_plan_t *plan)
{
if (needed)
{
hb_blob_t *dest_blob = serializer.copy_blob ();
hb_blob_t *dest_blob = _repack (serializer);
if (!dest_blob) return false;
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
result = c.plan->add_table (tag, dest_blob);
hb_blob_destroy (dest_blob);