Browse Source

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.
tags/n0.10
Stefano Sabatini 14 years ago
parent
commit
386aee6864
3 changed files with 76 additions and 11 deletions
  1. +26
    -0
      libavfilter/formats.c
  2. +12
    -0
      libavfilter/internal.h
  3. +38
    -11
      libavfilter/sink_buffer.c

+ 26
- 0
libavfilter/formats.c View File

@@ -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; \


+ 12
- 0
libavfilter/internal.h View File

@@ -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 */

/**


+ 38
- 11
libavfilter/sink_buffer.c View File

@@ -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,



Loading…
Cancel
Save