[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
|
||||
{
|
||||
const DeviceRecord *source_device_record;
|
||||
unsigned int size_device_record;
|
||||
hb_subset_plan_t *subset_plan;
|
||||
|
||||
inline void init(const DeviceRecord *source_device_record,
|
||||
unsigned int size_device_record,
|
||||
hb_subset_plan_t *subset_plan)
|
||||
{
|
||||
this->source_device_record = source_device_record;
|
||||
this->size_device_record = size_device_record;
|
||||
this->subset_plan = subset_plan;
|
||||
}
|
||||
|
||||
@ -57,11 +60,17 @@ struct DeviceRecord
|
||||
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];
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -133,9 +150,10 @@ struct hdmx
|
||||
for (unsigned int i = 0; i < source_hdmx->num_records; i++)
|
||||
{
|
||||
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);
|
||||
|
BIN
test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a
Normal file
BIN
test/api/fonts/crash-ccc61c92d589f895174cdef6ff2e3b20e9999a1a
Normal file
Binary file not shown.
@ -50,6 +50,28 @@ test_subset_hdmx_simple_subset (void)
|
||||
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
|
||||
test_subset_hdmx_noop (void)
|
||||
{
|
||||
@ -75,6 +97,7 @@ main (int argc, char **argv)
|
||||
hb_test_init (&argc, &argv);
|
||||
|
||||
hb_test_add (test_subset_hdmx_simple_subset);
|
||||
hb_test_add (test_subset_hdmx_invalid);
|
||||
hb_test_add (test_subset_hdmx_noop);
|
||||
|
||||
return hb_test_run();
|
||||
|
Loading…
Reference in New Issue
Block a user