diff mbox series

[FFmpeg-devel] avcodec/libx264: fix sei payload leaks on error

Message ID 20211101220350.700-1-jamrial@gmail.com
State Accepted
Commit f6ab103bb5c2dd494620f7a28ae232efe497a4d1
Headers show
Series [FFmpeg-devel] avcodec/libx264: fix sei payload leaks on error | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

James Almer Nov. 1, 2021, 10:03 p.m. UTC
Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/libx264.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

Comments

James Almer Nov. 3, 2021, 12:49 p.m. UTC | #1
On 11/1/2021 7:03 PM, James Almer wrote:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>   libavcodec/libx264.c | 23 +++++++++++++++++++----
>   1 file 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;

Will apply.
diff mbox series

Patch

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;