diff --git a/ChangeLog b/ChangeLog index bedbb941dc..c1526cec13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-02-22 Tim-Philipp Müller + + * gst-libs/gst/netbuffer/gstnetbuffer.c: + (notgst_buffer_copy_fields_in_place), (gst_netbuffer_copy): + Fix copying of GstNetBuffer (would crash before, or at least lead to + invalid memory access, #410772), for now by copying the GstBuffer copy + code from the core over here so we can copy the GstBuffer fields on a + provided buffer instance (of type GstNetBuffer in this case). Would be + better to fix this with some support by the core though (and in the long + run change the broken GstBuffer/GstMiniObject copy semantics, #393099). + + * tests/check/Makefile.am: + Enable unit test for GstNetBuffer. + 2007-02-22 Andy Wingo * gst-libs/gst/audio/gstbaseaudiosink.c diff --git a/gst-libs/gst/netbuffer/gstnetbuffer.c b/gst-libs/gst/netbuffer/gstnetbuffer.c index b41bee943a..141606ea9c 100644 --- a/gst-libs/gst/netbuffer/gstnetbuffer.c +++ b/gst-libs/gst/netbuffer/gstnetbuffer.c @@ -88,14 +88,52 @@ gst_netbuffer_finalize (GstNetBuffer * nbuf) GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf)); } +/* this is copy'n'pasted from _gst_buffer_copy() in lack of a better solution; + * keep in sync with _gst_buffer_copy() */ +static void +notgst_buffer_copy_fields_in_place (GstBuffer * copy, GstBuffer * buffer) +{ + guint mask; + + GST_LOG ("copying %p to %p", buffer, copy); + + /* copy relevant flags */ + mask = GST_BUFFER_FLAG_PREROLL | GST_BUFFER_FLAG_IN_CAPS | + GST_BUFFER_FLAG_DELTA_UNIT | GST_BUFFER_FLAG_DISCONT | + GST_BUFFER_FLAG_GAP; + GST_MINI_OBJECT_FLAGS (copy) |= GST_MINI_OBJECT_FLAGS (buffer) & mask; + + /* we simply copy everything from our parent */ + copy->data = g_memdup (buffer->data, buffer->size); + /* make sure it gets freed (even if the parent is subclassed, we return a + normal buffer) */ + copy->malloc_data = copy->data; + + copy->size = buffer->size; + + GST_BUFFER_TIMESTAMP (copy) = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_DURATION (copy) = GST_BUFFER_DURATION (buffer); + GST_BUFFER_OFFSET (copy) = GST_BUFFER_OFFSET (buffer); + GST_BUFFER_OFFSET_END (copy) = GST_BUFFER_OFFSET_END (buffer); + + if (GST_BUFFER_CAPS (buffer)) + GST_BUFFER_CAPS (copy) = gst_caps_ref (GST_BUFFER_CAPS (buffer)); + else + GST_BUFFER_CAPS (copy) = NULL; +} + static GstNetBuffer * gst_netbuffer_copy (GstNetBuffer * nbuf) { GstNetBuffer *copy; - copy = - (GstNetBuffer *) GST_MINI_OBJECT_CLASS (parent_class)-> - copy (GST_MINI_OBJECT (nbuf)); + copy = gst_netbuffer_new (); + + /* can't just chain up to parent_class::copy() because that will allocate + * a normal GstBuffer for us, so we'd lose the to/from fields and we don't + * want that */ + notgst_buffer_copy_fields_in_place (GST_BUFFER_CAST (copy), + GST_BUFFER_CAST (nbuf)); memcpy (©->to, &nbuf->to, sizeof (nbuf->to)); memcpy (©->from, &nbuf->from, sizeof (nbuf->from)); diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 7e9aba1842..1c6f64385b 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -77,6 +77,7 @@ check_PROGRAMS = \ gst/typefindfunctions \ libs/audio \ libs/cddabasesrc \ + libs/netbuffer \ libs/tag \ libs/video \ libs/utils \ @@ -94,7 +95,7 @@ VALGRIND_TO_FIX = \ libs/video # these tests don't even pass -noinst_PROGRAMS = libs/netbuffer +noinst_PROGRAMS = AM_CFLAGS = $(GST_CFLAGS) $(GST_CHECK_CFLAGS) LDADD = $(GST_LIBS) $(GST_CHECK_LIBS)