value: Refactor parsing lists to allow trailing comas
authorThibault Saunier <tsaunier@igalia.com>
Wed, 11 Mar 2020 18:19:45 +0000 (15:19 -0300)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 12 Mar 2020 14:50:20 +0000 (14:50 +0000)
Before that commit `{test, }` wouldn't be accepted as an array
because of the trailing coma, the commit fixes that.

At the same time, the code has been refactored to avoid special casing
the first element of the list, making `{,}` or `<,>` valid lists.

gst/gstvalue.c
tests/check/gst/gstvalue.c

index 4b396cdb464f3f248f96ef11e2bc6ebfe990b29a..30f5b77a2fa9f96c8a692081fb4cc1390daa63b8 100644 (file)
@@ -2438,30 +2438,20 @@ _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
     return FALSE;
   s++;
 
-  while (g_ascii_isspace (*s))
-    s++;
-  if (*s == end) {
-    s++;
-    *after = s;
-    return TRUE;
-  }
-
-  ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
-  if (!ret)
-    return FALSE;
-
-  g_array_append_val (array, list_value);
-
   while (g_ascii_isspace (*s))
     s++;
 
   while (*s != end) {
-    if (*s != ',')
-      return FALSE;
-    s++;
-
-    while (g_ascii_isspace (*s))
+    if (*s == ',') {
       s++;
+      while (g_ascii_isspace (*s))
+        s++;
+
+      if (*s == ',')
+        return FALSE;
+
+      continue;
+    }
 
     memset (&list_value, 0, sizeof (list_value));
     ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
@@ -2469,8 +2459,12 @@ _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
       return FALSE;
 
     g_array_append_val (array, list_value);
+
     while (g_ascii_isspace (*s))
       s++;
+
+    if (*s != ',' && *s != end)
+      return FALSE;
   }
 
   s++;
index 4c898c72c88a4b9979fd33c386a774fab3eed1ac..eb1634d4f3f03a0aa09a3cf781bc89f35c3bbc9e 100644 (file)
@@ -3435,6 +3435,42 @@ GST_START_TEST (test_serialize_null_aray)
 
 GST_END_TEST;
 
+GST_START_TEST (test_deserialize_array)
+{
+  GValue value = { 0 };
+  const gchar *strings[] = {
+    "{ test, }",
+    "{ , }",
+    "{ test,, }",
+    "{ , , }",
+  };
+  gint results_size[] = { 1, 0, -1, -1 };       /* -1 means deserialization should fail */
+  int i;
+
+  for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
+    /* Workaround a bug in our parser that would lead to segfaults
+     * when deserializing container types using static strings */
+    gchar *str = g_strdup (strings[i]);
+    g_value_init (&value, GST_TYPE_LIST);
+
+    if (results_size[i] == -1) {
+      fail_if (gst_value_deserialize (&value, str),
+          "Should not be able to deserialize %s (%d) as list", str, i);
+    } else {
+      fail_unless (gst_value_deserialize (&value, str),
+          "could not deserialize %s (%d)", str, i);
+      fail_unless (gst_value_list_get_size (&value) == results_size[i],
+          "Wrong array size: %d. expected %d",
+          gst_value_array_get_size (&value), results_size[i]);
+    }
+
+    g_value_unset (&value);
+    g_free (str);
+  }
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_value_suite (void)
 {
@@ -3455,6 +3491,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_deserialize_gtype);
   tcase_add_test (tc_chain, test_deserialize_gtype_failures);
   tcase_add_test (tc_chain, test_deserialize_bitmask);
+  tcase_add_test (tc_chain, test_deserialize_array);
   tcase_add_test (tc_chain, test_serialize_flags);
   tcase_add_test (tc_chain, test_deserialize_flags);
   tcase_add_test (tc_chain, test_serialize_deserialize_format_enum);