diff options
author | Stefano Sabatini <stefano.sabatini-lala@poste.it> | 2011-07-01 16:31:16 +0200 |
---|---|---|
committer | Stefano Sabatini <stefano.sabatini-lala@poste.it> | 2011-07-07 00:36:50 +0200 |
commit | df8c675f487bc2cda2b22541cd8e5a6d8090374d (patch) | |
tree | d0bd7c0126370f946c902680d3be36b861a7525d /libavfilter/graphparser.c | |
parent | c3b6cc61e502b8df0d5bc6b9058dfc482a08d42a (diff) | |
download | ffmpeg-df8c675f487bc2cda2b22541cd8e5a6d8090374d.tar.gz |
graphparser: fix logic for updating the open_inputs/outputs in avfilter_graph_parse()
Create open_inputs and open_outputs structs if they are not provided by
the user, and free them before exit.
In particular, fix NULL pointer dereference and crash, in case the
passed open_inputs/outputs is NULL and the parsing failed.
Diffstat (limited to 'libavfilter/graphparser.c')
-rw-r--r-- | libavfilter/graphparser.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 214729edb7..edba731897 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -333,38 +333,40 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, } int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, - AVFilterInOut **open_inputs, AVFilterInOut **open_outputs, + AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx) { - int index = 0, ret; + int index = 0, ret = 0; char chr = 0; AVFilterInOut *curr_inputs = NULL; + AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; + AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; do { AVFilterContext *filter; const char *filterchain = filters; filters += strspn(filters, WHITESPACES); - if ((ret = parse_inputs(&filters, &curr_inputs, open_outputs, log_ctx)) < 0) - goto fail; + if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) + goto end; if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) - goto fail; + goto end; if (filter->input_count == 1 && !curr_inputs && !index) { /* First input can be omitted if it is "[in]" */ const char *tmp = "[in]"; - if ((ret = parse_inputs(&tmp, &curr_inputs, open_outputs, log_ctx)) < 0) - goto fail; + if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) + goto end; } - if ((ret = link_filter_inouts(filter, &curr_inputs, open_inputs, log_ctx)) < 0) - goto fail; + if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) + goto end; - if ((ret = parse_outputs(&filters, &curr_inputs, open_inputs, open_outputs, + if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; filters += strspn(filters, WHITESPACES); chr = *filters++; @@ -374,7 +376,7 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filterchain); ret = AVERROR(EINVAL); - goto fail; + goto end; } index++; } while (chr == ',' || chr == ';'); @@ -384,25 +386,29 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); - goto fail; + goto end; } - if (open_inputs && *open_inputs && !strcmp((*open_inputs)->name, "out") && curr_inputs) { + if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) { /* Last output can be omitted if it is "[out]" */ const char *tmp = "[out]"; - if ((ret = parse_outputs(&tmp, &curr_inputs, open_inputs, open_outputs, + if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) - goto fail; + goto end; } - return 0; - - fail: - for (; graph->filter_count > 0; graph->filter_count--) - avfilter_free(graph->filters[graph->filter_count - 1]); - av_freep(&graph->filters); - avfilter_inout_free(open_inputs); - avfilter_inout_free(open_outputs); +end: + /* clear open_in/outputs only if not passed as parameters */ + if (open_inputs_ptr) *open_inputs_ptr = open_inputs; + else avfilter_inout_free(&open_inputs); + if (open_outputs_ptr) *open_outputs_ptr = open_outputs; + else avfilter_inout_free(&open_outputs); avfilter_inout_free(&curr_inputs); + + if (ret < 0) { + for (; graph->filter_count > 0; graph->filter_count--) + avfilter_free(graph->filters[graph->filter_count - 1]); + av_freep(&graph->filters); + } return ret; } |