Commit 386aee68 authored by Stefano Sabatini's avatar Stefano Sabatini

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.
parent ab6603b1
...@@ -93,6 +93,32 @@ int ff_fmt_is_in(int fmt, const int *fmts) ...@@ -93,6 +93,32 @@ int ff_fmt_is_in(int fmt, const int *fmts)
return 0; 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() \ #define MAKE_FORMAT_LIST() \
AVFilterFormats *formats; \ AVFilterFormats *formats; \
int count = 0; \ int count = 0; \
......
...@@ -69,6 +69,18 @@ void ff_avfilter_default_free_buffer(AVFilterBuffer *buf); ...@@ -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. */ /** Tell is a format is contained in the provided list terminated by -1. */
int ff_fmt_is_in(int fmt, const int *fmts); 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 */ /* Functions to parse audio format arguments */
/** /**
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "libavutil/fifo.h" #include "libavutil/fifo.h"
#include "avfilter.h" #include "avfilter.h"
#include "buffersink.h" #include "buffersink.h"
#include "internal.h"
AVBufferSinkParams *av_buffersink_params_alloc(void) AVBufferSinkParams *av_buffersink_params_alloc(void)
{ {
...@@ -58,12 +59,12 @@ typedef struct { ...@@ -58,12 +59,12 @@ typedef struct {
AVFifoBuffer *fifo; ///< FIFO buffer of video frame references AVFifoBuffer *fifo; ///< FIFO buffer of video frame references
/* only used for video */ /* 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 */ /* only used for audio */
const enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE 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 int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1
const int *packing_fmts; ///< list of accepted packing formats, terminated by -1 int *packing_fmts; ///< list of accepted packing formats, terminated by -1
} BufferSinkContext; } BufferSinkContext;
#define FIFO_INIT_SIZE 8 #define FIFO_INIT_SIZE 8
...@@ -169,16 +170,26 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq ...@@ -169,16 +170,26 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq
return AVERROR(EINVAL); return AVERROR(EINVAL);
} else { } else {
#if FF_API_OLD_VSINK_API #if FF_API_OLD_VSINK_API
buf->pixel_fmts = (const enum PixelFormat *)opaque; const int *pixel_fmts = (const enum PixelFormat *)opaque;
#else #else
params = (AVBufferSinkParams *)opaque; params = (AVBufferSinkParams *)opaque;
buf->pixel_fmts = params->pixel_fmts; const int *pixel_fmts = params->pixel_fmts;
#endif #endif
buf->pixel_fmts = ff_copy_int_list(pixel_fmts);
if (!buf->pixel_fmts)
return AVERROR(ENOMEM);
} }
return common_init(ctx); 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) static int vsink_query_formats(AVFilterContext *ctx)
{ {
BufferSinkContext *buf = ctx->priv; BufferSinkContext *buf = ctx->priv;
...@@ -192,7 +203,7 @@ AVFilter avfilter_vsink_buffersink = { ...@@ -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."), .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
.priv_size = sizeof(BufferSinkContext), .priv_size = sizeof(BufferSinkContext),
.init = vsink_init, .init = vsink_init,
.uninit = common_uninit, .uninit = vsink_uninit,
.query_formats = vsink_query_formats, .query_formats = vsink_query_formats,
...@@ -225,13 +236,29 @@ static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaq ...@@ -225,13 +236,29 @@ static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaq
} else } else
params = (AVABufferSinkParams *)opaque; params = (AVABufferSinkParams *)opaque;
buf->sample_fmts = params->sample_fmts; buf->sample_fmts = ff_copy_int_list (params->sample_fmts);
buf->channel_layouts = params->channel_layouts; buf->channel_layouts = ff_copy_int64_list(params->channel_layouts);
buf->packing_fmts = params->packing_fmts; 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); 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) static int asink_query_formats(AVFilterContext *ctx)
{ {
BufferSinkContext *buf = ctx->priv; BufferSinkContext *buf = ctx->priv;
...@@ -256,7 +283,7 @@ AVFilter avfilter_asink_abuffersink = { ...@@ -256,7 +283,7 @@ AVFilter avfilter_asink_abuffersink = {
.name = "abuffersink", .name = "abuffersink",
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
.init = asink_init, .init = asink_init,
.uninit = common_uninit, .uninit = asink_uninit,
.priv_size = sizeof(BufferSinkContext), .priv_size = sizeof(BufferSinkContext),
.query_formats = asink_query_formats, .query_formats = asink_query_formats,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment