From 2c5a8cdb3106ae1759e04d6c80e571654efada62 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 26 Apr 2007 10:00:49 +0000 Subject: [PATCH] API: add gst_buffer_try_new_and_alloc() plus unit test (#431940). Original commit message from CVS: * docs/gst/gstreamer-sections.txt: * gst/gstbuffer.c: (gst_buffer_try_new_and_alloc): * gst/gstbuffer.h: * tests/check/gst/gstbuffer.c: (GST_START_TEST), (gst_buffer_suite): API: add gst_buffer_try_new_and_alloc() plus unit test (#431940). --- ChangeLog | 9 ++++++++ docs/gst/gstreamer-sections.txt | 1 + gst/gstbuffer.c | 49 ++++++++++++++++++++++++++++++++++++++++- gst/gstbuffer.h | 8 ++++--- tests/check/gst/gstbuffer.c | 46 +++++++++++++++++++++++++++++++++++++- 5 files changed, 108 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6f8b3c..0412667 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-04-26 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstbuffer.c: (gst_buffer_try_new_and_alloc): + * gst/gstbuffer.h: + * tests/check/gst/gstbuffer.c: (GST_START_TEST), + (gst_buffer_suite): + API: add gst_buffer_try_new_and_alloc() plus unit test (#431940). + 2007-04-26 Stefan Kost * gst/gstregistrybinary.c: (gst_registry_binary_write_cache), diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index f091ea5..096bb9a 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -157,6 +157,7 @@ GST_BUFFER_TRACE_NAME gst_buffer_new gst_buffer_new_and_alloc +gst_buffer_try_new_and_alloc gst_buffer_ref gst_buffer_unref diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 236263a..a9b65cc 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -305,7 +305,12 @@ gst_buffer_new (void) * @size: the size of the new buffer's data. * * Creates a newly allocated buffer with data of the given size. - * The buffer memory is not cleared. + * The buffer memory is not cleared. If the requested amount of + * memory can't be allocated, the program will abort. Use + * gst_buffer_try_new_and_alloc() if you want to handle this case + * gracefully or have gotten the size to allocate from an untrusted + * source such as a media stream. + * * * Note that when @size == 0, the buffer data pointer will be NULL. * @@ -329,6 +334,48 @@ gst_buffer_new_and_alloc (guint size) } /** + * gst_buffer_try_new_and_alloc: + * @size: the size of the new buffer's data. + * + * Tries to create a newly allocated buffer with data of the given size. If + * the requested amount of memory can't be allocated, NULL will be returned. + * The buffer memory is not cleared. + * + * Note that when @size == 0, the buffer data pointer will be NULL. + * + * MT safe. + * + * Returns: a new #GstBuffer, or NULL if the memory couldn't be allocated. + * + * Since: 0.10.13 + */ +GstBuffer * +gst_buffer_try_new_and_alloc (guint size) +{ + GstBuffer *newbuf; + guint8 *malloc_data; + + malloc_data = g_try_malloc (size); + + if (G_UNLIKELY (malloc_data == NULL && size != 0)) { + GST_CAT_WARNING (GST_CAT_BUFFER, "failed to allocate %d bytes", size); + return NULL; + } + + /* FIXME: there's no g_type_try_create_instance() in GObject yet, so this + * will still abort if a new GstBuffer structure can't be allocated */ + newbuf = gst_buffer_new (); + + GST_BUFFER_MALLOCDATA (newbuf) = malloc_data; + GST_BUFFER_DATA (newbuf) = malloc_data; + GST_BUFFER_SIZE (newbuf) = size; + + GST_CAT_LOG (GST_CAT_BUFFER, "new %p of size %d", newbuf, size); + + return newbuf; +} + +/** * gst_buffer_get_caps: * @buffer: a #GstBuffer. * diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h index 2c08fd7..7b05c46 100644 --- a/gst/gstbuffer.h +++ b/gst/gstbuffer.h @@ -267,10 +267,12 @@ struct _GstBufferClass { GstMiniObjectClass mini_object_class; }; +GType gst_buffer_get_type (void); + /* allocation */ -GType gst_buffer_get_type (void); -GstBuffer* gst_buffer_new (void); -GstBuffer* gst_buffer_new_and_alloc (guint size); +GstBuffer * gst_buffer_new (void); +GstBuffer * gst_buffer_new_and_alloc (guint size); +GstBuffer * gst_buffer_try_new_and_alloc (guint size); /** * gst_buffer_set_data: diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c index 7be0c52..792520e 100644 --- a/tests/check/gst/gstbuffer.c +++ b/tests/check/gst/gstbuffer.c @@ -20,6 +20,16 @@ * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_VALGRIND +# include +#else +# define RUNNING_ON_VALGRIND FALSE +#endif + #include GST_START_TEST (test_caps) @@ -401,7 +411,40 @@ GST_START_TEST (test_copy) GST_END_TEST; -Suite * +GST_START_TEST (test_try_new_and_alloc) +{ + GstBuffer *buf; + + /* special case: alloc of 0 bytes results in new buffer with NULL data */ + buf = gst_buffer_try_new_and_alloc (0); + fail_unless (buf != NULL); + fail_unless (GST_IS_BUFFER (buf)); + fail_unless (GST_BUFFER_SIZE (buf) == 0); + fail_unless (GST_BUFFER_DATA (buf) == NULL); + fail_unless (GST_BUFFER_MALLOCDATA (buf) == NULL); + gst_buffer_unref (buf); + + /* normal alloc should still work */ + buf = gst_buffer_try_new_and_alloc (640 * 480 * 4); + fail_unless (buf != NULL); + fail_unless (GST_IS_BUFFER (buf)); + fail_unless (GST_BUFFER_SIZE (buf) == (640 * 480 * 4)); + fail_unless (GST_BUFFER_DATA (buf) != NULL); + fail_unless (GST_BUFFER_MALLOCDATA (buf) != NULL); + GST_BUFFER_DATA (buf)[640 * 479 * 4 + 479] = 0xff; + gst_buffer_unref (buf); + + /* now this better fail (don't run in valgrind, it will abort + * or warn when passing silly arguments to malloc) */ + if (!RUNNING_ON_VALGRIND) { + buf = gst_buffer_try_new_and_alloc ((guint) - 1); + fail_unless (buf == NULL); + } +} + +GST_END_TEST; + +static Suite * gst_buffer_suite (void) { Suite *s = suite_create ("GstBuffer"); @@ -416,6 +459,7 @@ gst_buffer_suite (void) tcase_add_test (tc_chain, test_span); tcase_add_test (tc_chain, test_metadata_writable); tcase_add_test (tc_chain, test_copy); + tcase_add_test (tc_chain, test_try_new_and_alloc); return s; } -- 2.7.4