From e14297e1f1fe534d4511d08826acdd40a00c2462 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 17 Feb 2021 22:36:20 -0500 Subject: 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); -- cgit v1.2.1