[subset] Add a fix for segfault in hmtx/vmtx subsetting code.
authorGarret Rieger <grieger@google.com>
Tue, 20 Mar 2018 01:39:22 +0000 (18:39 -0700)
committerGarret Rieger <grieger@google.com>
Wed, 21 Mar 2018 01:47:36 +0000 (19:47 -0600)
src/hb-ot-hmtx-table.hh
test/api/test-subset-hmtx.c

index bff792a..2af9a5c 100644 (file)
@@ -118,6 +118,8 @@ struct hmtxvmtx
     LongMetric * old_metrics = (LongMetric *) source_table;
     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
     char * dest_pos = (char *) dest;
+
+    bool failed = false;
     for (unsigned int i = 0; i < gids.len; i++)
     {
       /* the last metric or the one for gids[i] */
@@ -138,7 +140,14 @@ struct hmtxvmtx
       }
       else
       {
-        FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
+       if (gids[i] >= _mtx.num_metrics)
+       {
+         DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
+                   gids[i], _mtx.num_metrics);
+         failed = true;
+         break;
+       }
+       FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
         if (i < num_advances)
         {
           /* dest needs a full LongMetric */
@@ -157,7 +166,7 @@ struct hmtxvmtx
     _mtx.fini ();
 
     // Amend header num hmetrics
-    if (unlikely (!subset_update_header (plan, num_advances)))
+    if (failed || unlikely (!subset_update_header (plan, num_advances)))
     {
       free (dest);
       return false;
index cb22497..0ed6256 100644 (file)
@@ -163,7 +163,8 @@ test_subset_invalid_hmtx (void)
 
   hb_subset_profile_t *profile = hb_subset_profile_create();
   hb_face_t *subset = hb_subset (face, profile, input);
-  g_assert (!subset);
+  g_assert (subset);
+  g_assert (subset == hb_face_get_empty ());
 
   hb_subset_input_destroy (input);
   hb_subset_profile_destroy (profile);