[subset] Fixed out of bounds read when subsetting hdmx.
This commit is contained in:
parent
e597436b99
commit
3531efdb4c
|
@ -43,12 +43,15 @@ struct DeviceRecord
|
||||||
struct SubsetView
|
struct SubsetView
|
||||||
{
|
{
|
||||||
const DeviceRecord *source_device_record;
|
const DeviceRecord *source_device_record;
|
||||||
|
unsigned int size_device_record;
|
||||||
hb_subset_plan_t *subset_plan;
|
hb_subset_plan_t *subset_plan;
|
||||||
|
|
||||||
inline void init(const DeviceRecord *source_device_record,
|
inline void init(const DeviceRecord *source_device_record,
|
||||||
|
unsigned int size_device_record,
|
||||||
hb_subset_plan_t *subset_plan)
|
hb_subset_plan_t *subset_plan)
|
||||||
{
|
{
|
||||||
this->source_device_record = source_device_record;
|
this->source_device_record = source_device_record;
|
||||||
|
this->size_device_record = size_device_record;
|
||||||
this->subset_plan = subset_plan;
|
this->subset_plan = subset_plan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +60,17 @@ struct DeviceRecord
|
||||||
return this->subset_plan->gids_to_retain_sorted.len;
|
return this->subset_plan->gids_to_retain_sorted.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const HBUINT8& operator [] (unsigned int i) const
|
inline const HBUINT8* operator [] (unsigned int i) const
|
||||||
{
|
{
|
||||||
if (unlikely (i >= len())) return Null(HBUINT8);
|
if (unlikely (i >= len())) return nullptr;
|
||||||
hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
|
hb_codepoint_t gid = this->subset_plan->gids_to_retain_sorted [i];
|
||||||
return this->source_device_record->widths[gid];
|
|
||||||
|
const HBUINT8* width = &(this->source_device_record->widths[gid]);
|
||||||
|
|
||||||
|
if (width < ((const HBUINT8 *) this->source_device_record) + size_device_record)
|
||||||
|
return width;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,7 +94,15 @@ struct DeviceRecord
|
||||||
this->max_width.set (subset_view.source_device_record->max_width);
|
this->max_width.set (subset_view.source_device_record->max_width);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < subset_view.len(); i++)
|
for (unsigned int i = 0; i < subset_view.len(); i++)
|
||||||
widths[i].set (subset_view[i]);
|
{
|
||||||
|
const HBUINT8 *width = subset_view[i];
|
||||||
|
if (!width)
|
||||||
|
{
|
||||||
|
DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
|
||||||
|
return_trace (false);
|
||||||
|
}
|
||||||
|
widths[i].set (*width);
|
||||||
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
@ -133,9 +150,10 @@ struct hdmx
|
||||||
for (unsigned int i = 0; i < source_hdmx->num_records; i++)
|
for (unsigned int i = 0; i < source_hdmx->num_records; i++)
|
||||||
{
|
{
|
||||||
DeviceRecord::SubsetView subset_view;
|
DeviceRecord::SubsetView subset_view;
|
||||||
subset_view.init (&(*source_hdmx)[i], plan);
|
subset_view.init (&(*source_hdmx)[i], source_hdmx->size_device_record, plan);
|
||||||
|
|
||||||
c->start_embed<DeviceRecord> ()->serialize (c, subset_view);
|
if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
|
||||||
|
return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
|
Binary file not shown.
|
@ -50,6 +50,28 @@ test_subset_hdmx_simple_subset (void)
|
||||||
hb_face_destroy (face_ac);
|
hb_face_destroy (face_ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_subset_hdmx_invalid (void)
|
||||||
|
{
|
||||||
|
hb_face_t *face = hb_subset_test_open_font("fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a");
|
||||||
|
|
||||||
|
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
||||||
|
hb_set_t *codepoints = hb_subset_input_unicode_set (input);
|
||||||
|
hb_set_add (codepoints, 'a');
|
||||||
|
hb_set_add (codepoints, 'b');
|
||||||
|
hb_set_add (codepoints, 'c');
|
||||||
|
|
||||||
|
hb_subset_profile_t *profile = hb_subset_profile_create();
|
||||||
|
hb_face_t *subset = hb_subset (face, profile, input);
|
||||||
|
g_assert (subset);
|
||||||
|
g_assert (subset == hb_face_get_empty ());
|
||||||
|
|
||||||
|
hb_subset_input_destroy (input);
|
||||||
|
hb_subset_profile_destroy (profile);
|
||||||
|
hb_face_destroy (subset);
|
||||||
|
hb_face_destroy (face);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_subset_hdmx_noop (void)
|
test_subset_hdmx_noop (void)
|
||||||
{
|
{
|
||||||
|
@ -75,6 +97,7 @@ main (int argc, char **argv)
|
||||||
hb_test_init (&argc, &argv);
|
hb_test_init (&argc, &argv);
|
||||||
|
|
||||||
hb_test_add (test_subset_hdmx_simple_subset);
|
hb_test_add (test_subset_hdmx_simple_subset);
|
||||||
|
hb_test_add (test_subset_hdmx_invalid);
|
||||||
hb_test_add (test_subset_hdmx_noop);
|
hb_test_add (test_subset_hdmx_noop);
|
||||||
|
|
||||||
return hb_test_run();
|
return hb_test_run();
|
||||||
|
|
Loading…
Reference in New Issue