From e838007d096cefd0f500cde86a4ca550930ca40b Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Fri, 6 Oct 2017 21:59:03 +0200 Subject: [PATCH] gstbuffer: fix meta removal in gst_buffer_foreach_meta When updating the linked list, prev->next = next is correct if prev is actually updated after being set to the head of the list at the start. https://bugzilla.gnome.org/show_bug.cgi?id=788617 --- gst/gstbuffer.c | 4 ++++ tests/check/gst/gstmeta.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 3077543..34ca517 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -2370,12 +2370,16 @@ gst_buffer_foreach_meta (GstBuffer * buffer, GstBufferForeachMetaFunc func, else prev->next = next; + prev = next; + /* call free_func if any */ if (info->free_func) info->free_func (m, buffer); /* and free the slice */ g_slice_free1 (ITEM_SIZE (info), walk); + } else { + prev = walk; } if (!res) break; diff --git a/tests/check/gst/gstmeta.c b/tests/check/gst/gstmeta.c index 9e88eb7..65cf835 100644 --- a/tests/check/gst/gstmeta.c +++ b/tests/check/gst/gstmeta.c @@ -314,6 +314,57 @@ GST_START_TEST (test_meta_locked) GST_END_TEST; +static gboolean +foreach_meta_remove_one (GstBuffer * buffer, GstMeta ** meta, + gpointer to_remove) +{ + if (*meta == to_remove) { + *meta = NULL; + } + + return TRUE; +} + +static gint +count_buffer_meta (GstBuffer * buffer) +{ + gint ret = 0; + gpointer state = NULL; + + while (gst_buffer_iterate_meta (buffer, &state)) + ret++; + + return ret; +} + +GST_START_TEST (test_meta_foreach_remove_one) +{ + GstBuffer *buffer; + GstMetaTest *meta1, *meta2, *meta3; + + buffer = gst_buffer_new_and_alloc (4); + fail_if (buffer == NULL); + + /* add some metadata */ + meta1 = GST_META_TEST_ADD (buffer); + fail_if (meta1 == NULL); + meta2 = GST_META_TEST_ADD (buffer); + fail_if (meta2 == NULL); + meta3 = GST_META_TEST_ADD (buffer); + fail_if (meta3 == NULL); + + fail_unless_equals_int (count_buffer_meta (buffer), 3); + + gst_buffer_foreach_meta (buffer, foreach_meta_remove_one, meta1); + + fail_unless_equals_int (count_buffer_meta (buffer), 2); + + /* clean up */ + gst_buffer_unref (buffer); +} + +GST_END_TEST; + GST_START_TEST (test_meta_iterate) { GstBuffer *buffer; @@ -421,6 +472,7 @@ gst_buffermeta_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_meta_test); tcase_add_test (tc_chain, test_meta_locked); + tcase_add_test (tc_chain, test_meta_foreach_remove_one); tcase_add_test (tc_chain, test_meta_iterate); return s; -- 2.7.4