[pango/fix-attribute-splicing] Fix a corner-case of pango_attr_list_splice




commit e14297e1f1fe534d4511d08826acdd40a00c2462
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Feb 17 22:36:20 2021 -0500

    Fix a corner-case of pango_attr_list_splice
    
    When the 'other' list contains attributes that are
    unlimited or exceed the range given to pango_attr_list_splice,
    those attributes were 'leaking' out of the range. The visible
    effect of this is that the underline of preedit text extends
    outside the preedit in some GTK entries.
    
    Fix this by clipping the inserted attributes to the range.
    The documentation is not very explicit about this, but I believe
    this is the expected behavior.
    
    Tests included.

 pango/pango-attributes.c |  7 +++++--
 tests/testattributes.c   | 38 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 41 insertions(+), 4 deletions(-)
---
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 3ef76a70..8f23fe77 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1769,6 +1769,7 @@ pango_attr_list_splice (PangoAttrList *list,
 {
   guint i, p;
   guint upos, ulen;
+  guint end;
 
   g_return_if_fail (list != NULL);
   g_return_if_fail (other != NULL);
@@ -1783,6 +1784,8 @@ pango_attr_list_splice (PangoAttrList *list,
  */
 #define CLAMP_ADD(a,b) (((a) + (b) < (a)) ? G_MAXUINT : (a) + (b))
 
+  end = CLAMP_ADD (upos, ulen);
+
   if (list->attributes)
     for (i = 0, p = list->attributes->len; i < p; i++)
       {
@@ -1811,8 +1814,8 @@ pango_attr_list_splice (PangoAttrList *list,
   for (i = 0, p = other->attributes->len; i < p; i++)
     {
       PangoAttribute *attr = pango_attribute_copy (g_ptr_array_index (other->attributes, i));
-      attr->start_index = CLAMP_ADD (attr->start_index, upos);
-      attr->end_index = CLAMP_ADD (attr->end_index, upos);
+      attr->start_index = MIN (CLAMP_ADD (attr->start_index, upos), end);
+      attr->end_index = MIN (CLAMP_ADD (attr->end_index, upos), end);
 
       /* Same as above, the attribute could be squashed to zero-length; here
        * pango_attr_list_change() will take care of deleting it.
diff --git a/tests/testattributes.c b/tests/testattributes.c
index 6131f38c..8e632017 100644
--- a/tests/testattributes.c
+++ b/tests/testattributes.c
@@ -325,14 +325,47 @@ test_list_splice2 (void)
 
   pango_attr_list_splice (list, other, 11, 5);
 
-  assert_attr_list (list, "[11,-1]size=10\n");
+  assert_attr_list (list, "[11,16]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");
+  assert_attr_list (list, "[11,21]size=10\n");
+
+  pango_attr_list_unref (other);
+  pango_attr_list_unref (list);
+}
+
+/* Test that attributes in other aren't leaking out in pango_attr_list_splice */
+static void
+test_list_splice3 (void)
+{
+  PangoAttrList *list;
+  PangoAttrList *other;
+  PangoAttribute *attr;
+
+  list = pango_attr_list_new ();
+  other = pango_attr_list_new ();
+
+  attr = pango_attr_variant_new (PANGO_VARIANT_SMALL_CAPS);
+  attr->start_index = 10;
+  attr->end_index = 30;
+  pango_attr_list_insert (list, attr);
+
+  attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+  attr->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING;
+  attr->end_index = PANGO_ATTR_INDEX_TO_TEXT_END;
+  pango_attr_list_insert (other, attr);
+
+  assert_attr_list (list, "[10,30]variant=1\n");
+  assert_attr_list (other, "[0,-1]weight=700\n");
+
+  pango_attr_list_splice (list, other, 20, 5);
+
+  assert_attr_list (list, "[10,35]variant=1\n"
+                          "[20,25]weight=700\n");
 
   pango_attr_list_unref (other);
   pango_attr_list_unref (list);
@@ -1043,6 +1076,7 @@ main (int argc, char *argv[])
   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/splice3", test_list_splice3);
   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);


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