diff mbox

[FFmpeg-devel,1/2] avcodec/cbs_h264: Automatically free SEI payload on error

Message ID 20190911221830.61819-1-andreas.rheinhardt@gmail.com
State Accepted
Commit f83ac5fd793f6464020777da6802803048b97fc6
Headers show

Commit Message

Andreas Rheinhardt Sept. 11, 2019, 10:18 p.m. UTC
If adding an SEI message to an access unit fails, said SEI message was
not touched, so that the caller had to free any data associated with it
that might need to be freed. But given that ff_cbs_h264_add_sei_message
can simply call cbs_h264_free_sei_payload, one can easily free
the content of the SEI payload.

This fixes a memleak when inserting a user data unregistered string for
h264_metadata fails.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavcodec/cbs_h264.h  |  5 ++++-
 libavcodec/cbs_h2645.c | 16 +++++++++++-----
 2 files changed, 15 insertions(+), 6 deletions(-)

Comments

Mark Thompson Sept. 24, 2019, 3:25 p.m. UTC | #1
On 11/09/2019 23:18, Andreas Rheinhardt wrote:
> If adding an SEI message to an access unit fails, said SEI message was
> not touched, so that the caller had to free any data associated with it
> that might need to be freed. But given that ff_cbs_h264_add_sei_message
> can simply call cbs_h264_free_sei_payload, one can easily free
> the content of the SEI payload.
> 
> This fixes a memleak when inserting a user data unregistered string for
> h264_metadata fails.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
> ---
>  libavcodec/cbs_h264.h  |  5 ++++-
>  libavcodec/cbs_h2645.c | 16 +++++++++++-----
>  2 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
> index b39e7480c9..9f7c2a0d30 100644
> --- a/libavcodec/cbs_h264.h
> +++ b/libavcodec/cbs_h264.h
> @@ -468,10 +468,13 @@ typedef struct CodedBitstreamH264Context {
>  
>  /**
>   * Add an SEI message to an access unit.
> + *
> + * On success, the payload will be owned by a unit in access_unit;
> + * on failure, the content of the payload will be freed.
>   */
>  int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
>                                  CodedBitstreamFragment *access_unit,
> -                                const H264RawSEIPayload *payload);
> +                                H264RawSEIPayload *payload);
>  
>  /**
>   * Delete an SEI message from an access unit.
> diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
> index 8da8421e47..2dc261f7a5 100644
> --- a/libavcodec/cbs_h2645.c
> +++ b/libavcodec/cbs_h2645.c
> @@ -1586,7 +1586,7 @@ const CodedBitstreamType ff_cbs_type_h265 = {
>  
>  int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
>                                  CodedBitstreamFragment *au,
> -                                const H264RawSEIPayload *payload)
> +                                H264RawSEIPayload *payload)
>  {
>      H264RawSEI *sei = NULL;
>      int err, i;
> @@ -1608,8 +1608,10 @@ int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
>          AVBufferRef *sei_ref;
>  
>          sei = av_mallocz(sizeof(*sei));
> -        if (!sei)
> -            return AVERROR(ENOMEM);
> +        if (!sei) {
> +            err = AVERROR(ENOMEM);
> +            goto fail;
> +        }
>  
>          sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
>          sei->nal_unit_header.nal_ref_idc   = 0;
> @@ -1618,7 +1620,8 @@ int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
>                                     &cbs_h264_free_sei, NULL, 0);
>          if (!sei_ref) {
>              av_freep(&sei);
> -            return AVERROR(ENOMEM);
> +            err = AVERROR(ENOMEM);
> +            goto fail;
>          }
>  
>          for (i = 0; i < au->nb_units; i++) {
> @@ -1631,13 +1634,16 @@ int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
>                                           sei, sei_ref);
>          av_buffer_unref(&sei_ref);
>          if (err < 0)
> -            return err;
> +            goto fail;
>      }
>  
>      memcpy(&sei->payload[sei->payload_count], payload, sizeof(*payload));
>      ++sei->payload_count;
>  
>      return 0;
> +fail:
> +    cbs_h264_free_sei_payload(payload);
> +    return err;
>  }
>  
>  void ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx,
> 

Hmm - this rather makes me think that the API to the function isn't the right one.

Still, it's only used in one place right now and it fixes the immediate problem.  So LGTM, applied.

Thanks,

- Mark
diff mbox

Patch

diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
index b39e7480c9..9f7c2a0d30 100644
--- a/libavcodec/cbs_h264.h
+++ b/libavcodec/cbs_h264.h
@@ -468,10 +468,13 @@  typedef struct CodedBitstreamH264Context {
 
 /**
  * Add an SEI message to an access unit.
+ *
+ * On success, the payload will be owned by a unit in access_unit;
+ * on failure, the content of the payload will be freed.
  */
 int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
                                 CodedBitstreamFragment *access_unit,
-                                const H264RawSEIPayload *payload);
+                                H264RawSEIPayload *payload);
 
 /**
  * Delete an SEI message from an access unit.
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 8da8421e47..2dc261f7a5 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -1586,7 +1586,7 @@  const CodedBitstreamType ff_cbs_type_h265 = {
 
 int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
                                 CodedBitstreamFragment *au,
-                                const H264RawSEIPayload *payload)
+                                H264RawSEIPayload *payload)
 {
     H264RawSEI *sei = NULL;
     int err, i;
@@ -1608,8 +1608,10 @@  int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
         AVBufferRef *sei_ref;
 
         sei = av_mallocz(sizeof(*sei));
-        if (!sei)
-            return AVERROR(ENOMEM);
+        if (!sei) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
 
         sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
         sei->nal_unit_header.nal_ref_idc   = 0;
@@ -1618,7 +1620,8 @@  int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
                                    &cbs_h264_free_sei, NULL, 0);
         if (!sei_ref) {
             av_freep(&sei);
-            return AVERROR(ENOMEM);
+            err = AVERROR(ENOMEM);
+            goto fail;
         }
 
         for (i = 0; i < au->nb_units; i++) {
@@ -1631,13 +1634,16 @@  int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
                                          sei, sei_ref);
         av_buffer_unref(&sei_ref);
         if (err < 0)
-            return err;
+            goto fail;
     }
 
     memcpy(&sei->payload[sei->payload_count], payload, sizeof(*payload));
     ++sei->payload_count;
 
     return 0;
+fail:
+    cbs_h264_free_sei_payload(payload);
+    return err;
 }
 
 void ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx,