summaryrefslogtreecommitdiff
path: root/libavcodec/libx264.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2021-11-01 18:57:56 -0300
committerJames Almer <jamrial@gmail.com>2021-11-04 22:59:55 -0300
commitf6ab103bb5c2dd494620f7a28ae232efe497a4d1 (patch)
tree9dd2329c9a5d3ec0a7d254d6b862f52a0aea5ac1 /libavcodec/libx264.c
parentd2379bd6a03bc57eb9cc027a75f21086474422fe (diff)
avcodec/libx264: fix sei payload leaks on error
Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavcodec/libx264.c')
-rw-r--r--libavcodec/libx264.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 21f434d06d..0766b4a950 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -293,6 +293,18 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame)
}
}
+static void free_picture(AVCodecContext *ctx)
+{
+ X264Context *x4 = ctx->priv_data;
+ x264_picture_t *pic = &x4->pic;
+
+ for (int i = 0; i < pic->extra_sei.num_payloads; i++)
+ av_free(pic->extra_sei.payloads[i].payload);
+ av_freep(&pic->extra_sei.payloads);
+ av_freep(&pic->prop.quant_offsets);
+ pic->extra_sei.num_payloads = 0;
+}
+
static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
int *got_packet)
{
@@ -396,15 +408,17 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
roi = (const AVRegionOfInterest*)sd->data;
roi_size = roi->self_size;
if (!roi_size || sd->size % roi_size != 0) {
+ free_picture(ctx);
av_log(ctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n");
return AVERROR(EINVAL);
}
nb_rois = sd->size / roi_size;
qoffsets = av_calloc(mbx * mby, sizeof(*qoffsets));
- if (!qoffsets)
+ if (!qoffsets) {
+ free_picture(ctx);
return AVERROR(ENOMEM);
-
+ }
// This list must be iterated in reverse because the first
// region in the list applies when regions overlap.
for (int i = nb_rois - 1; i >= 0; i--) {
@@ -420,6 +434,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
if (roi->qoffset.den == 0) {
av_free(qoffsets);
+ free_picture(ctx);
av_log(ctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n");
return AVERROR(EINVAL);
}
@@ -452,7 +467,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
continue;
tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload));
if (!tmp) {
- av_freep(&x4->pic.prop.quant_offsets);
+ free_picture(ctx);
return AVERROR(ENOMEM);
}
sei->payloads = tmp;
@@ -460,7 +475,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
sei_payload = &sei->payloads[sei->num_payloads];
sei_payload->payload = av_memdup(side_data->data, side_data->size);
if (!sei_payload->payload) {
- av_freep(&x4->pic.prop.quant_offsets);
+ free_picture(ctx);
return AVERROR(ENOMEM);
}
sei_payload->payload_size = side_data->size;