[FFmpeg-devel] [PATCH] sink_buffer: copy list of provided formats in the context
Stefano Sabatini
stefasab at gmail.com
Tue Dec 20 13:37:24 CET 2011
A list of formats may have been dynamically created by the calling code,
and thus should not be referenced by the sink buffer context.
Avoid possible invalid data reference.
---
libavfilter/formats.c | 26 ++++++++++++++++++++++++++
libavfilter/internal.h | 12 ++++++++++++
libavfilter/sink_buffer.c | 45 ++++++++++++++++++++++++++++++++++-----------
3 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index ff4d49d..4743a81 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -93,6 +93,32 @@ int ff_fmt_is_in(int fmt, const int *fmts)
return 0;
}
+#define COPY_INT_LIST(list_copy, list, type) { \
+ int count = 0; \
+ if (list) \
+ for (count = 0; list[count] != -1; count++) \
+ ; \
+ list_copy = av_malloc((count+1) * sizeof(type)); \
+ if (list_copy) { \
+ memcpy(list_copy, list, sizeof(type) * count); \
+ list_copy[count] = -1; \
+ } \
+}
+
+int *ff_copy_int_list(const int * const list)
+{
+ int *ret = NULL;
+ COPY_INT_LIST(ret, list, int);
+ return ret;
+}
+
+int64_t *ff_copy_int64_list(const int64_t * const list)
+{
+ int64_t *ret = NULL;
+ COPY_INT_LIST(ret, list, int64_t);
+ return ret;
+}
+
#define MAKE_FORMAT_LIST() \
AVFilterFormats *formats; \
int count = 0; \
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 9f28a83..cba6ab8 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -69,6 +69,18 @@ void ff_avfilter_default_free_buffer(AVFilterBuffer *buf);
/** Tell is a format is contained in the provided list terminated by -1. */
int ff_fmt_is_in(int fmt, const int *fmts);
+/**
+ * Return a copy of a list of integers terminated by -1, or NULL in
+ * case of copy failure.
+ */
+int *ff_copy_int_list(const int * const list);
+
+/**
+ * Return a copy of a list of 64 bits integers, or NULL in case of
+ * copy failure.
+ */
+int64_t *ff_copy_int64_list(const int64_t * const list);
+
/* Functions to parse audio format arguments */
/**
diff --git a/libavfilter/sink_buffer.c b/libavfilter/sink_buffer.c
index e572385..106ba19 100644
--- a/libavfilter/sink_buffer.c
+++ b/libavfilter/sink_buffer.c
@@ -26,6 +26,7 @@
#include "libavutil/fifo.h"
#include "avfilter.h"
#include "buffersink.h"
+#include "internal.h"
AVBufferSinkParams *av_buffersink_params_alloc(void)
{
@@ -58,12 +59,12 @@ typedef struct {
AVFifoBuffer *fifo; ///< FIFO buffer of video frame references
/* only used for video */
- const enum PixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1
+ enum PixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1
/* only used for audio */
- const enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE
- const int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1
- const int *packing_fmts; ///< list of accepted packing formats, terminated by -1
+ enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE
+ int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1
+ int *packing_fmts; ///< list of accepted packing formats, terminated by -1
} BufferSinkContext;
#define FIFO_INIT_SIZE 8
@@ -169,16 +170,26 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq
return AVERROR(EINVAL);
} else {
#if FF_API_OLD_VSINK_API
- buf->pixel_fmts = (const enum PixelFormat *)opaque;
+ const int *pixel_fmts = (const enum PixelFormat *)opaque;
#else
params = (AVBufferSinkParams *)opaque;
- buf->pixel_fmts = params->pixel_fmts;
+ const int *pixel_fmts = params->pixel_fmts;
#endif
+ buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
+ if (!buf->pixel_fmts)
+ return AVERROR(ENOMEM);
}
return common_init(ctx);
}
+static av_cold void vsink_uninit(AVFilterContext *ctx)
+{
+ BufferSinkContext *buf = ctx->priv;
+ av_freep(&buf->pixel_fmts);
+ return common_uninit(ctx);
+}
+
static int vsink_query_formats(AVFilterContext *ctx)
{
BufferSinkContext *buf = ctx->priv;
@@ -192,7 +203,7 @@ AVFilter avfilter_vsink_buffersink = {
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
.priv_size = sizeof(BufferSinkContext),
.init = vsink_init,
- .uninit = common_uninit,
+ .uninit = vsink_uninit,
.query_formats = vsink_query_formats,
@@ -225,13 +236,25 @@ static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaq
} else
params = (AVABufferSinkParams *)opaque;
- buf->sample_fmts = params->sample_fmts;
- buf->channel_layouts = params->channel_layouts;
- buf->packing_fmts = params->packing_fmts;
+ buf->sample_fmts = ff_copy_int_list (params->sample_fmts);
+ buf->channel_layouts = ff_copy_int64_list(params->channel_layouts);
+ buf->packing_fmts = ff_copy_int_list (params->packing_fmts);
+ if (!buf->sample_fmts || !buf->channel_layouts || !buf->sample_fmts)
+ return AVERROR(ENOMEM);
return common_init(ctx);
}
+static av_cold void asink_uninit(AVFilterContext *ctx)
+{
+ BufferSinkContext *buf = ctx->priv;
+
+ av_freep(&buf->sample_fmts);
+ av_freep(&buf->channel_layouts);
+ av_freep(&buf->packing_fmts);
+ return common_uninit(ctx);
+}
+
static int asink_query_formats(AVFilterContext *ctx)
{
BufferSinkContext *buf = ctx->priv;
@@ -256,7 +279,7 @@ AVFilter avfilter_asink_abuffersink = {
.name = "abuffersink",
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
.init = asink_init,
- .uninit = common_uninit,
+ .uninit = asink_uninit,
.priv_size = sizeof(BufferSinkContext),
.query_formats = asink_query_formats,
--
1.7.5.4
More information about the ffmpeg-devel
mailing list