[pango/empty-attr-list] Fix crashes with empty attribute lists



commit 01d35fa30ac1b63e5b6c13a663def2efa1a6dcd8
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jun 22 08:15:35 2020 -0400

    Fix crashes with empty attribute lists
    
    There were a few cases left where empty attribute
    lists could lead to crashes. This was observed causing
    crashes in gnumeric.
    
    Testcases included.

 pango/pango-attributes.c | 106 ++++++++++++++++++++++++-----------------------
 tests/testattributes.c   |  51 +++++++++++++++++++++++
 2 files changed, 105 insertions(+), 52 deletions(-)
---
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 37443346..218ffade 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1697,40 +1697,41 @@ pango_attr_list_update (PangoAttrList *list,
 {
   guint i, p;
 
-  for (i = 0, p = list->attributes->len; i < p; i++)
-    {
-      PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
-
-      if (attr->start_index >= pos &&
-          attr->end_index < pos + remove)
-        {
-          pango_attribute_destroy (attr);
-          g_ptr_array_remove_index (list->attributes, i);
-          i--; /* Look at this index again */
-          p--;
-          continue;
-        }
-
-      if (attr->start_index >= pos &&
-          attr->start_index < pos + remove)
-        {
-          attr->start_index = pos + add;
-        }
-      else if (attr->start_index >= pos + remove)
-        {
-          attr->start_index += add - remove;
-        }
+  if (list->attributes)
+    for (i = 0, p = list->attributes->len; i < p; i++)
+      {
+        PangoAttribute *attr = g_ptr_array_index (list->attributes, i);
 
-      if (attr->end_index >= pos &&
+        if (attr->start_index >= pos &&
           attr->end_index < pos + remove)
-        {
-          attr->end_index = pos;
-        }
-      else if (attr->end_index >= pos + remove)
-        {
-          attr->end_index += add - remove;
-        }
-    }
+          {
+            pango_attribute_destroy (attr);
+            g_ptr_array_remove_index (list->attributes, i);
+            i--; /* Look at this index again */
+            p--;
+            continue;
+          }
+
+        if (attr->start_index >= pos &&
+            attr->start_index < pos + remove)
+          {
+            attr->start_index = pos + add;
+          }
+        else if (attr->start_index >= pos + remove)
+          {
+            attr->start_index += add - remove;
+          }
+
+        if (attr->end_index >= pos &&
+            attr->end_index < pos + remove)
+          {
+            attr->end_index = pos;
+          }
+        else if (attr->end_index >= pos + remove)
+          {
+            attr->end_index += add - remove;
+          }
+      }
 }
 
 /**
@@ -1775,26 +1776,27 @@ pango_attr_list_splice (PangoAttrList *list,
  */
 #define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
 
-  for (i = 0, p = list->attributes->len; i < p; i++)
-    {
-      PangoAttribute *attr = g_ptr_array_index (list->attributes, i);;
-
-      if (attr->start_index <= upos)
-       {
-         if (attr->end_index > upos)
-           attr->end_index = CLAMP_ADD (attr->end_index, ulen);
-       }
-      else
-       {
-         /* This could result in a zero length attribute if it
-          * gets squashed up against G_MAXUINT, but deleting such
-          * an element could (in theory) suprise the caller, so
-          * we don't delete it.
-          */
-         attr->start_index = CLAMP_ADD (attr->start_index, ulen);
-         attr->end_index = CLAMP_ADD (attr->end_index, ulen);
-        }
-    }
+  if (list->attributes)
+    for (i = 0, p = list->attributes->len; i < p; i++)
+      {
+        PangoAttribute *attr = g_ptr_array_index (list->attributes, i);;
+
+        if (attr->start_index <= upos)
+          {
+            if (attr->end_index > upos)
+              attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+          }
+        else
+          {
+            /* This could result in a zero length attribute if it
+             * gets squashed up against G_MAXUINT, but deleting such
+             * an element could (in theory) suprise the caller, so
+             * we don't delete it.
+             */
+            attr->start_index = CLAMP_ADD (attr->start_index, ulen);
+            attr->end_index = CLAMP_ADD (attr->end_index, ulen);
+         }
+      }
 
   if (!other->attributes || other->attributes->len == 0)
     return;
diff --git a/tests/testattributes.c b/tests/testattributes.c
index 4a8bc577..8db42b4a 100644
--- a/tests/testattributes.c
+++ b/tests/testattributes.c
@@ -303,6 +303,41 @@ test_list_splice (void)
   pango_attr_list_unref (base);
 }
 
+/* Test that empty lists work in pango_attr_list_splice */
+static void
+test_list_splice2 (void)
+{
+  PangoAttrList *list;
+  PangoAttrList *other;
+  PangoAttribute *attr;
+
+  list = pango_attr_list_new ();
+  other = pango_attr_list_new ();
+
+  pango_attr_list_splice (list, other, 11, 5);
+
+  g_assert_null (pango_attr_list_get_attributes (list));
+
+  attr = pango_attr_size_new (10);
+  attr->start_index = 0;
+  attr->end_index = -1;
+  pango_attr_list_insert (other, attr);
+
+  pango_attr_list_splice (list, other, 11, 5);
+
+  assert_attr_list (list, "[11,-1]size=10\n");
+
+  pango_attr_list_unref (other);
+  other = pango_attr_list_new ();
+
+  pango_attr_list_splice (list, other, 11, 5);
+
+  assert_attr_list (list, "[11,-1]size=10\n");
+
+  pango_attr_list_unref (other);
+  pango_attr_list_unref (list);
+}
+
 static gboolean
 never_true (PangoAttribute *attribute, gpointer user_data)
 {
@@ -623,6 +658,20 @@ test_list_update (void)
   pango_attr_list_unref (list);
 }
 
+/* Test that empty lists work in pango_attr_list_update */
+static void
+test_list_update2 (void)
+{
+  PangoAttrList *list;
+
+  list = pango_attr_list_new ();
+  pango_attr_list_update (list, 8, 10, 20);
+
+  g_assert_null (pango_attr_list_get_attributes (list));
+
+  pango_attr_list_unref (list);
+}
+
 static void
 test_list_equal (void)
 {
@@ -905,8 +954,10 @@ main (int argc, char *argv[])
   g_test_add_func ("/attributes/list/basic", test_list);
   g_test_add_func ("/attributes/list/change", test_list_change);
   g_test_add_func ("/attributes/list/splice", test_list_splice);
+  g_test_add_func ("/attributes/list/splice2", test_list_splice2);
   g_test_add_func ("/attributes/list/filter", test_list_filter);
   g_test_add_func ("/attributes/list/update", test_list_update);
+  g_test_add_func ("/attributes/list/update2", test_list_update2);
   g_test_add_func ("/attributes/list/equal", test_list_equal);
   g_test_add_func ("/attributes/list/insert", test_insert);
   g_test_add_func ("/attributes/list/merge", test_merge);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]