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




commit 0af597202fdf11de8467fd12f496142ff1ce2ff9
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 9c9cd4fa..b607445a 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1756,6 +1756,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);
@@ -1770,6 +1771,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++)
       {
@@ -1798,8 +1801,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]