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.
... | ... |
@@ -93,6 +93,32 @@ int ff_fmt_is_in(int fmt, const int *fmts) |
93 | 93 |
return 0; |
94 | 94 |
} |
95 | 95 |
|
96 |
+#define COPY_INT_LIST(list_copy, list, type) { \ |
|
97 |
+ int count = 0; \ |
|
98 |
+ if (list) \ |
|
99 |
+ for (count = 0; list[count] != -1; count++) \ |
|
100 |
+ ; \ |
|
101 |
+ list_copy = av_calloc(count+1, sizeof(type)); \ |
|
102 |
+ if (list_copy) { \ |
|
103 |
+ memcpy(list_copy, list, sizeof(type) * count); \ |
|
104 |
+ list_copy[count] = -1; \ |
|
105 |
+ } \ |
|
106 |
+} |
|
107 |
+ |
|
108 |
+int *ff_copy_int_list(const int * const list) |
|
109 |
+{ |
|
110 |
+ int *ret = NULL; |
|
111 |
+ COPY_INT_LIST(ret, list, int); |
|
112 |
+ return ret; |
|
113 |
+} |
|
114 |
+ |
|
115 |
+int64_t *ff_copy_int64_list(const int64_t * const list) |
|
116 |
+{ |
|
117 |
+ int64_t *ret = NULL; |
|
118 |
+ COPY_INT_LIST(ret, list, int64_t); |
|
119 |
+ return ret; |
|
120 |
+} |
|
121 |
+ |
|
96 | 122 |
#define MAKE_FORMAT_LIST() \ |
97 | 123 |
AVFilterFormats *formats; \ |
98 | 124 |
int count = 0; \ |
... | ... |
@@ -69,6 +69,18 @@ void ff_avfilter_default_free_buffer(AVFilterBuffer *buf); |
69 | 69 |
/** Tell is a format is contained in the provided list terminated by -1. */ |
70 | 70 |
int ff_fmt_is_in(int fmt, const int *fmts); |
71 | 71 |
|
72 |
+/** |
|
73 |
+ * Return a copy of a list of integers terminated by -1, or NULL in |
|
74 |
+ * case of copy failure. |
|
75 |
+ */ |
|
76 |
+int *ff_copy_int_list(const int * const list); |
|
77 |
+ |
|
78 |
+/** |
|
79 |
+ * Return a copy of a list of 64-bit integers, or NULL in case of |
|
80 |
+ * copy failure. |
|
81 |
+ */ |
|
82 |
+int64_t *ff_copy_int64_list(const int64_t * const list); |
|
83 |
+ |
|
72 | 84 |
/* Functions to parse audio format arguments */ |
73 | 85 |
|
74 | 86 |
/** |
... | ... |
@@ -26,6 +26,7 @@ |
26 | 26 |
#include "libavutil/fifo.h" |
27 | 27 |
#include "avfilter.h" |
28 | 28 |
#include "buffersink.h" |
29 |
+#include "internal.h" |
|
29 | 30 |
|
30 | 31 |
AVBufferSinkParams *av_buffersink_params_alloc(void) |
31 | 32 |
{ |
... | ... |
@@ -58,12 +59,12 @@ typedef struct { |
58 | 58 |
AVFifoBuffer *fifo; ///< FIFO buffer of video frame references |
59 | 59 |
|
60 | 60 |
/* only used for video */ |
61 |
- const enum PixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 |
|
61 |
+ enum PixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 |
|
62 | 62 |
|
63 | 63 |
/* only used for audio */ |
64 |
- const enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE |
|
65 |
- const int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 |
|
66 |
- const int *packing_fmts; ///< list of accepted packing formats, terminated by -1 |
|
64 |
+ enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE |
|
65 |
+ int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 |
|
66 |
+ int *packing_fmts; ///< list of accepted packing formats, terminated by -1 |
|
67 | 67 |
} BufferSinkContext; |
68 | 68 |
|
69 | 69 |
#define FIFO_INIT_SIZE 8 |
... | ... |
@@ -169,16 +170,26 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq |
169 | 169 |
return AVERROR(EINVAL); |
170 | 170 |
} else { |
171 | 171 |
#if FF_API_OLD_VSINK_API |
172 |
- buf->pixel_fmts = (const enum PixelFormat *)opaque; |
|
172 |
+ const int *pixel_fmts = (const enum PixelFormat *)opaque; |
|
173 | 173 |
#else |
174 | 174 |
params = (AVBufferSinkParams *)opaque; |
175 |
- buf->pixel_fmts = params->pixel_fmts; |
|
175 |
+ const int *pixel_fmts = params->pixel_fmts; |
|
176 | 176 |
#endif |
177 |
+ buf->pixel_fmts = ff_copy_int_list(pixel_fmts); |
|
178 |
+ if (!buf->pixel_fmts) |
|
179 |
+ return AVERROR(ENOMEM); |
|
177 | 180 |
} |
178 | 181 |
|
179 | 182 |
return common_init(ctx); |
180 | 183 |
} |
181 | 184 |
|
185 |
+static av_cold void vsink_uninit(AVFilterContext *ctx) |
|
186 |
+{ |
|
187 |
+ BufferSinkContext *buf = ctx->priv; |
|
188 |
+ av_freep(&buf->pixel_fmts); |
|
189 |
+ return common_uninit(ctx); |
|
190 |
+} |
|
191 |
+ |
|
182 | 192 |
static int vsink_query_formats(AVFilterContext *ctx) |
183 | 193 |
{ |
184 | 194 |
BufferSinkContext *buf = ctx->priv; |
... | ... |
@@ -192,7 +203,7 @@ AVFilter avfilter_vsink_buffersink = { |
192 | 192 |
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), |
193 | 193 |
.priv_size = sizeof(BufferSinkContext), |
194 | 194 |
.init = vsink_init, |
195 |
- .uninit = common_uninit, |
|
195 |
+ .uninit = vsink_uninit, |
|
196 | 196 |
|
197 | 197 |
.query_formats = vsink_query_formats, |
198 | 198 |
|
... | ... |
@@ -225,13 +236,29 @@ static av_cold int asink_init(AVFilterContext *ctx, const char *args, void *opaq |
225 | 225 |
} else |
226 | 226 |
params = (AVABufferSinkParams *)opaque; |
227 | 227 |
|
228 |
- buf->sample_fmts = params->sample_fmts; |
|
229 |
- buf->channel_layouts = params->channel_layouts; |
|
230 |
- buf->packing_fmts = params->packing_fmts; |
|
228 |
+ buf->sample_fmts = ff_copy_int_list (params->sample_fmts); |
|
229 |
+ buf->channel_layouts = ff_copy_int64_list(params->channel_layouts); |
|
230 |
+ buf->packing_fmts = ff_copy_int_list (params->packing_fmts); |
|
231 |
+ if (!buf->sample_fmts || !buf->channel_layouts || !buf->sample_fmts) { |
|
232 |
+ av_freep(&buf->sample_fmts); |
|
233 |
+ av_freep(&buf->channel_layouts); |
|
234 |
+ av_freep(&buf->packing_fmts); |
|
235 |
+ return AVERROR(ENOMEM); |
|
236 |
+ } |
|
231 | 237 |
|
232 | 238 |
return common_init(ctx); |
233 | 239 |
} |
234 | 240 |
|
241 |
+static av_cold void asink_uninit(AVFilterContext *ctx) |
|
242 |
+{ |
|
243 |
+ BufferSinkContext *buf = ctx->priv; |
|
244 |
+ |
|
245 |
+ av_freep(&buf->sample_fmts); |
|
246 |
+ av_freep(&buf->channel_layouts); |
|
247 |
+ av_freep(&buf->packing_fmts); |
|
248 |
+ return common_uninit(ctx); |
|
249 |
+} |
|
250 |
+ |
|
235 | 251 |
static int asink_query_formats(AVFilterContext *ctx) |
236 | 252 |
{ |
237 | 253 |
BufferSinkContext *buf = ctx->priv; |
... | ... |
@@ -256,7 +283,7 @@ AVFilter avfilter_asink_abuffersink = { |
256 | 256 |
.name = "abuffersink", |
257 | 257 |
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), |
258 | 258 |
.init = asink_init, |
259 |
- .uninit = common_uninit, |
|
259 |
+ .uninit = asink_uninit, |
|
260 | 260 |
.priv_size = sizeof(BufferSinkContext), |
261 | 261 |
.query_formats = asink_query_formats, |
262 | 262 |
|