summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-02-17 22:36:20 -0500
committerMatthias Clasen <mclasen@redhat.com>2021-02-17 23:32:04 -0500
commite14297e1f1fe534d4511d08826acdd40a00c2462 (patch)
tree7541bb338377f758f1eb3225e3a8a330b072b85b
parent3fea9968434c7d6c0b73c481d27d5e2cfe71fda1 (diff)
downloadpango-fix-attribute-splicing.tar.gz
Fix a corner-case of pango_attr_list_splicefix-attribute-splicing
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.
-rw-r--r--pango/pango-attributes.c7
-rw-r--r--tests/testattributes.c38
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);