aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-04-02 14:17:56 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2021-04-02 18:09:26 +0200
commit9bf2b32da048732ad79e075dfefd40777e9f935a (patch)
tree6376071fc7f8ca6a8554ec63c9e806a52e76a387
parent8081a0b10f5325b60e885d8823593485019b8a18 (diff)
downloadffmpeg-9bf2b32da048732ad79e075dfefd40777e9f935a.tar.gz
avcodec/bsf: Fix segfault when freeing half-allocated BSF
When allocating a BSF fails, it could happen that the BSF's close function has been called despite a failure to allocate the private data. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
-rw-r--r--libavcodec/bsf.c39
1 files changed, 20 insertions, 19 deletions
diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
index d71bc32584..157984bd9a 100644
--- a/libavcodec/bsf.c
+++ b/libavcodec/bsf.c
@@ -45,14 +45,15 @@ void av_bsf_free(AVBSFContext **pctx)
return;
ctx = *pctx;
- if (ctx->filter->close)
- ctx->filter->close(ctx);
+ if (ctx->internal) {
+ if (ctx->filter->close)
+ ctx->filter->close(ctx);
+ av_packet_free(&ctx->internal->buffer_pkt);
+ av_freep(&ctx->internal);
+ }
if (ctx->filter->priv_class && ctx->priv_data)
av_opt_free(ctx->priv_data);
- if (ctx->internal)
- av_packet_free(&ctx->internal->buffer_pkt);
- av_freep(&ctx->internal);
av_freep(&ctx->priv_data);
avcodec_parameters_free(&ctx->par_in);
@@ -110,20 +111,6 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
ret = AVERROR(ENOMEM);
goto fail;
}
-
- bsfi = av_mallocz(sizeof(*bsfi));
- if (!bsfi) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- ctx->internal = bsfi;
-
- bsfi->buffer_pkt = av_packet_alloc();
- if (!bsfi->buffer_pkt) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
/* allocate priv data and init private options */
if (filter->priv_data_size) {
ctx->priv_data = av_mallocz(filter->priv_data_size);
@@ -136,6 +123,20 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
av_opt_set_defaults(ctx->priv_data);
}
}
+ /* Allocate AVBSFInternal; must happen after priv_data has been allocated
+ * so that a filter->close needing priv_data is never called without. */
+ bsfi = av_mallocz(sizeof(*bsfi));
+ if (!bsfi) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ ctx->internal = bsfi;
+
+ bsfi->buffer_pkt = av_packet_alloc();
+ if (!bsfi->buffer_pkt) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
*pctx = ctx;
return 0;