summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-06-22 08:15:35 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-06-22 08:15:35 -0400
commit01d35fa30ac1b63e5b6c13a663def2efa1a6dcd8 (patch)
treef5a5fc5ba01f2a7cc18e57ddf7663393da97894d
parent2a44077091bfe8680a12194d79f90e0443a06ad8 (diff)
downloadpango-01d35fa30ac1b63e5b6c13a663def2efa1a6dcd8.tar.gz
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.
-rw-r--r--pango/pango-attributes.c106
-rw-r--r--tests/testattributes.c51
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);