gstvalue: Don't loop forever when serializing invalid flag
authorOlivier CrĂȘte <olivier.crete@collabora.com>
Mon, 1 Aug 2022 18:00:20 +0000 (14:00 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 25 Aug 2022 22:27:51 +0000 (22:27 +0000)
The serialization code would loop forever if an invalid flag was sent into it.

With unit test for this corner case.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2823>

subprojects/gstreamer/gst/gstvalue.c
subprojects/gstreamer/tests/check/gst/gstvalue.c

index d6ee925..543f8d3 100644 (file)
@@ -4195,15 +4195,23 @@ gst_value_serialize_gflags (const GValue * value)
   result = g_strdup ("");
   while (flags) {
     fl = g_flags_get_first_value (klass, flags);
-    if (fl != NULL) {
-      tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
-      g_free (result);
-      result = tmp;
-      first = FALSE;
-
-      /* clear flag */
-      flags &= ~fl->value;
+    if (fl == NULL) {
+      if (flags) {
+        g_critical ("Could not serialize invalid flags 0x%x of type %s",
+            flags, G_VALUE_TYPE_NAME (value));
+        g_free (result);
+        result = g_strdup ("0");
+      }
+      break;
     }
+
+    tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
+    g_free (result);
+    result = tmp;
+    first = FALSE;
+
+    /* clear flag */
+    flags &= ~fl->value;
   }
   g_type_class_unref (klass);
 
index b86eef4..3a4ccfb 100644 (file)
@@ -447,6 +447,31 @@ GST_START_TEST (test_serialize_flags)
 
 GST_END_TEST;
 
+GST_START_TEST (test_serialize_flags_invalid)
+{
+  GValue value = { 0 };
+  gchar *string;
+
+  g_value_init (&value, GST_TYPE_SEEK_FLAGS);
+
+  /* Invalid value */
+  g_value_set_flags (&value, 1 << 20);
+  ASSERT_CRITICAL (string = gst_value_serialize (&value));
+  fail_if (string == NULL, "could not serialize invalid flags");
+  fail_unless (strcmp (string, "0") == 0,
+      "resulting value is %s, not 0, for invalid flags", string);
+  g_free (string);
+
+  /* Valid & invalid value */
+  g_value_set_flags (&value, GST_SEEK_FLAG_FLUSH | 1 << 20);
+  ASSERT_CRITICAL (string = gst_value_serialize (&value));
+  fail_if (string == NULL, "could not serialize invalid flags");
+  fail_unless (strcmp (string, "0") == 0,
+      "resulting value is %s, not 0, for invalid flags", string);
+  g_free (string);
+}
+
+GST_END_TEST;
 
 GST_START_TEST (test_deserialize_flags)
 {
@@ -3937,6 +3962,7 @@ gst_value_suite (void)
   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_serialize_flags_invalid);
   tcase_add_test (tc_chain, test_deserialize_flags);
   tcase_add_test (tc_chain, test_serialize_deserialize_format_enum);
   tcase_add_test (tc_chain, test_serialize_deserialize_value_array);