[FFmpeg-devel] [PATCH 4/7] avformat/vvc: Fix crash on allocation failure, avoid allocations

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Sun Jun 9 00:13:58 EEST 2024


Nuo Mi:
> On Wed, Jun 5, 2024 at 7:41 PM Andreas Rheinhardt <
> andreas.rheinhardt at outlook.com> wrote:
> 
>> This is the VVC version of 8b5d15530127fea54e934043a64653859de07353.
>>
>> (Hint: This ensures that the order of NALU arrays is OPI-VPS-SPS-PPS-
>> Prefix-SEI-Suffix-SEI, regardless of the order in the original
>> extradata. I hope this is right.)
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
>> ---
>>  libavformat/vvc.c | 169 ++++++++++++++++++++--------------------------
>>  1 file changed, 73 insertions(+), 96 deletions(-)
>>
>> diff --git a/libavformat/vvc.c b/libavformat/vvc.c
>> index 679bb07a4d..819ee02e2c 100644
>> --- a/libavformat/vvc.c
>> +++ b/libavformat/vvc.c
>> @@ -32,6 +32,16 @@
>>  #include "avio_internal.h"
>>  #include "vvc.h"
>>
>> +enum {
>> +    OPI_INDEX,
>> +    VPS_INDEX,
>> +    SPS_INDEX,
>> +    PPS_INDEX,
>> +    SEI_PREFIX_INDEX,
>> +    SEI_SUFFIX_INDEX,
>> +    NB_ARRAYS
>> +};
>> +
>>  typedef struct VVCCNALUnitArray {
>>      uint8_t array_completeness;
>>      uint8_t NAL_unit_type;
>> @@ -67,7 +77,7 @@ typedef struct VVCDecoderConfigurationRecord {
>>      uint16_t max_picture_height;
>>      uint16_t avg_frame_rate;
>>      uint8_t num_of_arrays;
>> -    VVCCNALUnitArray *array;
>> +    VVCCNALUnitArray arrays[NB_ARRAYS];
>>  } VVCDecoderConfigurationRecord;
>>
>>  static void vvcc_update_ptl(VVCDecoderConfigurationRecord *vvcc,
>> @@ -432,32 +442,11 @@ static void nal_unit_parse_header(GetBitContext *gb,
>> uint8_t *nal_type)
>>
>>  static int vvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
>>                                     uint8_t nal_type, int
>> ps_array_completeness,
>> -                                   VVCDecoderConfigurationRecord *vvcc)
>> +                                   VVCCNALUnitArray *array)
>>  {
>>      int ret;
>> -    uint8_t index;
>>      uint16_t num_nalus;
>> -    VVCCNALUnitArray *array;
>> -
>> -    for (index = 0; index < vvcc->num_of_arrays; index++)
>> -        if (vvcc->array[index].NAL_unit_type == nal_type)
>> -            break;
>> -
>> -    if (index >= vvcc->num_of_arrays) {
>> -        uint8_t i;
>> -
>> -        ret =
>> -            av_reallocp_array(&vvcc->array, index + 1,
>> -                              sizeof(VVCCNALUnitArray));
>> -        if (ret < 0)
>> -            return ret;
>> -
>> -        for (i = vvcc->num_of_arrays; i <= index; i++)
>> -            memset(&vvcc->array[i], 0, sizeof(VVCCNALUnitArray));
>> -        vvcc->num_of_arrays = index + 1;
>> -    }
>>
>> -    array = &vvcc->array[index];
>>      num_nalus = array->num_nalus;
>>
>>      ret = av_reallocp_array(&array->nal_unit, num_nalus + 1,
>> sizeof(uint8_t *));
>> @@ -504,7 +493,8 @@ static int vvcc_array_add_nal_unit(uint8_t *nal_buf,
>> uint32_t nal_size,
>>
>>  static int vvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
>>                               int ps_array_completeness,
>> -                             VVCDecoderConfigurationRecord *vvcc)
>> +                             VVCDecoderConfigurationRecord *vvcc,
>> +                             unsigned array_idx)
>>  {
>>      int ret = 0;
>>      GetBitContext gbc;
>> @@ -529,18 +519,15 @@ static int vvcc_add_nal_unit(uint8_t *nal_buf,
>> uint32_t nal_size,
>>       * vvcc. Perhaps the SEI playload type should be checked
>>       * and non-declarative SEI messages discarded?
>>       */
>> -    switch (nal_type) {
>> -    case VVC_OPI_NUT:
>> -    case VVC_VPS_NUT:
>> -    case VVC_SPS_NUT:
>> -    case VVC_PPS_NUT:
>> -    case VVC_PREFIX_SEI_NUT:
>> -    case VVC_SUFFIX_SEI_NUT:
>> -        ret = vvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
>> -                                      ps_array_completeness, vvcc);
>> -        if (ret < 0)
>> -            goto end;
>> -        else if (nal_type == VVC_VPS_NUT)
>> +    ret = vvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
>> +                                  ps_array_completeness,
>> +                                  &vvcc->arrays[array_idx]);
>> +    if (ret < 0)
>> +        goto end;
>> +    if (vvcc->arrays[array_idx].num_nalus == 1)
>> +        vvcc->num_of_arrays++;
>> +
>> +        if (nal_type == VVC_VPS_NUT)
>>              ret = vvcc_parse_vps(&gbc, vvcc);
>>          else if (nal_type == VVC_SPS_NUT)
>>              ret = vvcc_parse_sps(&gbc, vvcc);
>> @@ -551,11 +538,6 @@ static int vvcc_add_nal_unit(uint8_t *nal_buf,
>> uint32_t nal_size,
>>          }
>>          if (ret < 0)
>>              goto end;
>> -        break;
>> -    default:
>> -        ret = AVERROR_INVALIDDATA;
>> -        goto end;
>> -    }
>>
>>    end:
>>      av_free(rbsp_buf);
>> @@ -572,22 +554,21 @@ static void vvcc_init(VVCDecoderConfigurationRecord
>> *vvcc)
>>
>>  static void vvcc_close(VVCDecoderConfigurationRecord *vvcc)
>>  {
>> -    uint8_t i;
>> +    for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc->arrays); i++) {
>> +        VVCCNALUnitArray *const array = &vvcc->arrays[i];
>>
>> -    for (i = 0; i < vvcc->num_of_arrays; i++) {
>> -        vvcc->array[i].num_nalus = 0;
>> -        av_freep(&vvcc->array[i].nal_unit);
>> -        av_freep(&vvcc->array[i].nal_unit_length);
>> +        array->num_nalus = 0;
>> +        av_freep(&array->nal_unit);
>> +        av_freep(&array->nal_unit_length);
>>      }
>>
>>      vvcc->num_of_arrays = 0;
>> -    av_freep(&vvcc->array);
>>  }
>>
>>  static int vvcc_write(AVIOContext *pb, VVCDecoderConfigurationRecord
>> *vvcc)
>>  {
>>      uint8_t i;
>> -    uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
>> +    uint16_t vps_count = 0, sps_count = 0, pps_count = 0;
>>      /*
>>       * It's unclear how to properly compute these fields, so
>>       * let's always set them to values meaning 'unspecified'.
>> @@ -672,40 +653,33 @@ static int vvcc_write(AVIOContext *pb,
>> VVCDecoderConfigurationRecord *vvcc)
>>      av_log(NULL, AV_LOG_TRACE,
>>             "num_of_arrays:                       %" PRIu8 "\n",
>>             vvcc->num_of_arrays);
>> -    for (i = 0; i < vvcc->num_of_arrays; i++) {
>> +    for (unsigned i = 0; i < FF_ARRAY_ELEMS(vvcc->arrays); i++) {
>>
> this will shadow the "uint8_t i"
> 

I just sent a patch for this (and for fixing the comment).

- Andreas



More information about the ffmpeg-devel mailing list