diff options
author | Stefano Sabatini <stefasab@gmail.com> | 2011-12-20 13:08:57 +0100 |
---|---|---|
committer | Stefano Sabatini <stefasab@gmail.com> | 2011-12-22 10:09:42 +0100 |
commit | 386aee6864c5cfc438785d2421b2f056450da014 (patch) | |
tree | b18e4771036f3dc6bd01271a7fa4d6c7bc1197d7 /libavfilter | |
parent | ab6603b1d8d7d15542a9e1bafa580c4f3798c428 (diff) | |
download | ffmpeg-386aee6864c5cfc438785d2421b2f056450da014.tar.gz |
sink_buffer: copy list of provided formats in the context
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.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/formats.c | 26 | ||||
-rw-r--r-- | libavfilter/internal.h | 12 | ||||
-rw-r--r-- | libavfilter/sink_buffer.c | 49 |
3 files changed, 76 insertions, 11 deletions
diff --git a/libavfilter/formats.c b/libavfilter/formats.c index ff4d49dd5d..fa2c1be4bb 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_calloc(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 9f28a839df..227fe6243d 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-bit 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 e572385419..926362bef8 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,29 @@ 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) { + av_freep(&buf->sample_fmts); + av_freep(&buf->channel_layouts); + av_freep(&buf->packing_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 +283,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, |