From 741482085e5c09375014801b8b643497b62aae1f Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 25 Oct 2018 11:14:22 +0100 Subject: [PATCH 1/2] test-gvariant: Add test for ^ay, ^&ay, ^aay, ^a&ay This will exhibit bugs in g_variant_valist_free_nnp() as these types are not properly handled. --- glib/tests/gvariant.c | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index de8e42d0b..ce8c31481 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -3055,6 +3055,81 @@ test_varargs (void) g_free (strv); } + { + const gchar *strvector[] = {"/hello", "/world", NULL}; + const gchar *test_strs[] = {"/foo", "/bar", "/baz" }; + GVariantBuilder builder; + GVariantIter *array; + GVariantIter tuple; + const gchar **strv; + gchar **my_strv; + GVariant *value; + gchar *str; + gint i; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aaay")); + g_variant_builder_add (&builder, "^aay", strvector); + g_variant_builder_add (&builder, "^aay", strvector); + g_variant_builder_add (&builder, "^aay", strvector); + value = g_variant_new ("aaay", &builder); + g_variant_iter_init (&tuple, value); + i = 0; + while (g_variant_iter_loop (&tuple, "^aay", &my_strv)) { + i++; + } + g_assert (i == 3); + + /* start over */ + g_variant_iter_init (&tuple, value); + i = 0; + while (g_variant_iter_loop (&tuple, "^a&ay", &strv)) { + i++; + } + g_assert (i == 3); + g_variant_unref (value); + + /* next test */ + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay")); + g_variant_builder_add (&builder, "^ay", "/foo"); + g_variant_builder_add (&builder, "^ay", "/bar"); + g_variant_builder_add (&builder, "^ay", "/baz"); + value = g_variant_new("(aay^aay^a&ay)", &builder, strvector, strvector); + g_variant_iter_init (&tuple, value); + g_variant_iter_next (&tuple, "aay", &array); + + i = 0; + while (g_variant_iter_loop (array, "^ay", &str)) + g_assert_cmpstr (str, ==, test_strs[i++]); + g_assert (i == 3); + + g_variant_iter_free (array); + + /* start over */ + g_variant_iter_init (&tuple, value); + g_variant_iter_next (&tuple, "aay", &array); + + i = 0; + while (g_variant_iter_loop (array, "^&ay", &str)) + g_assert_cmpstr (str, ==, test_strs[i++]); + g_assert (i == 3); + + g_variant_iter_free (array); + + g_variant_iter_next (&tuple, "^a&ay", &strv); + g_variant_iter_next (&tuple, "^aay", &my_strv); + + g_assert_cmpstr (strv[0], ==, "/hello"); + g_assert_cmpstr (strv[1], ==, "/world"); + g_assert (strv[2] == NULL); + g_assert_cmpstr (my_strv[0], ==, "/hello"); + g_assert_cmpstr (my_strv[1], ==, "/world"); + g_assert (my_strv[2] == NULL); + + g_variant_unref (value); + g_strfreev (my_strv); + g_free (strv); + } + { const gchar *strvector[] = {"/hello", "/world", NULL}; const gchar *test_strs[] = {"/foo", "/bar", "/baz" }; From 46e493437c5a71143faeb171e0eb01fc16f37166 Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 25 Oct 2018 11:22:31 +0100 Subject: [PATCH 2/2] gvariant: Handle ^ay, ^&ay, ^aay, ^a&ay in g_variant_valist_free_nnp g_variant_valist_free_nnp does not take into account ^*ay, which causes crash when trying to use these types together with g_variant_iter_loop(). --- glib/gvariant.c | 10 +++++++++- glib/tests/gvariant.c | 17 ++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/glib/gvariant.c b/glib/gvariant.c index 2c9f951b3..d45b487ad 100644 --- a/glib/gvariant.c +++ b/glib/gvariant.c @@ -4662,7 +4662,15 @@ g_variant_valist_free_nnp (const gchar *str, break; case '^': - if (str[2] != '&') /* '^as', '^ao' */ + if (g_str_has_suffix (str, "y")) + { + if (str[2] != 'a') /* '^a&ay', '^ay' */ + g_free (ptr); + else if (str[1] == 'a') /* '^aay' */ + g_strfreev (ptr); + break; /* '^&ay' */ + } + else if (str[2] != '&') /* '^as', '^ao' */ g_strfreev (ptr); else /* '^a&s', '^a&o' */ g_free (ptr); diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index ce8c31481..e8fa25d34 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -3072,28 +3072,27 @@ test_varargs (void) g_variant_builder_add (&builder, "^aay", strvector); g_variant_builder_add (&builder, "^aay", strvector); value = g_variant_new ("aaay", &builder); - g_variant_iter_init (&tuple, value); + array = g_variant_iter_new (value); i = 0; - while (g_variant_iter_loop (&tuple, "^aay", &my_strv)) { - i++; - } + while (g_variant_iter_loop (array, "^aay", &my_strv)) + i++; g_assert (i == 3); /* start over */ - g_variant_iter_init (&tuple, value); + g_variant_iter_init (array, value); i = 0; - while (g_variant_iter_loop (&tuple, "^a&ay", &strv)) { - i++; - } + while (g_variant_iter_loop (array, "^a&ay", &strv)) + i++; g_assert (i == 3); g_variant_unref (value); + g_variant_iter_free (array); /* next test */ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay")); g_variant_builder_add (&builder, "^ay", "/foo"); g_variant_builder_add (&builder, "^ay", "/bar"); g_variant_builder_add (&builder, "^ay", "/baz"); - value = g_variant_new("(aay^aay^a&ay)", &builder, strvector, strvector); + value = g_variant_new ("(aay^aay^a&ay)", &builder, strvector, strvector); g_variant_iter_init (&tuple, value); g_variant_iter_next (&tuple, "aay", &array);