[FFmpeg-cvslog] avformat/iamf_parse: add checks to parameter definition durations

James Almer git at videolan.org
Fri Dec 20 03:15:34 EET 2024


ffmpeg | branch: release/7.1 | James Almer <jamrial at gmail.com> | Wed Dec 11 23:27:00 2024 -0300| [888a6b54bcc8ab395ebc214d764ceefaa1232d87] | committer: James Almer

avformat/iamf_parse: add checks to parameter definition durations

Section 3.6.1 of the IAMF spec states "When constant_subblock_duration is equal to 0, the summation of all
subblock_duration in this parameter block SHALL be equal to duration.".

Signed-off-by: James Almer <jamrial at gmail.com>
(cherry picked from commit d38fc25519cf12a9212dadcba1258fc176ffbade)

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=888a6b54bcc8ab395ebc214d764ceefaa1232d87
---

 libavformat/iamf_parse.c  | 14 ++++++++++++--
 libavformat/iamf_reader.c | 15 +++++++++++++--
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c
index decd4bc437..57ccf1c199 100644
--- a/libavformat/iamf_parse.c
+++ b/libavformat/iamf_parse.c
@@ -496,6 +496,7 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
     AVIAMFParamDefinition *param;
     unsigned int parameter_id, parameter_rate, mode;
     unsigned int duration = 0, constant_subblock_duration = 0, nb_subblocks = 0;
+    unsigned int total_duration = 0;
     size_t param_size;
 
     parameter_id = ffio_read_leb(pb);
@@ -516,8 +517,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
         constant_subblock_duration = ffio_read_leb(pb);
         if (constant_subblock_duration == 0)
             nb_subblocks = ffio_read_leb(pb);
-        else
+        else {
             nb_subblocks = duration / constant_subblock_duration;
+            total_duration = duration;
+        }
     }
 
     param = av_iamf_param_definition_alloc(type, nb_subblocks, &param_size);
@@ -528,8 +531,10 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
         void *subblock = av_iamf_param_definition_get_subblock(param, i);
         unsigned int subblock_duration = constant_subblock_duration;
 
-        if (constant_subblock_duration == 0)
+        if (constant_subblock_duration == 0) {
             subblock_duration = ffio_read_leb(pb);
+            total_duration += subblock_duration;
+        }
 
         switch (type) {
         case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
@@ -557,6 +562,11 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
         }
     }
 
+    if (!mode && !constant_subblock_duration && total_duration != duration) {
+        av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
+        return AVERROR_INVALIDDATA;
+    }
+
     param->parameter_id = parameter_id;
     param->parameter_rate = parameter_rate;
     param->duration = duration;
diff --git a/libavformat/iamf_reader.c b/libavformat/iamf_reader.c
index b00bb997ca..7ad61cb246 100644
--- a/libavformat/iamf_reader.c
+++ b/libavformat/iamf_reader.c
@@ -109,6 +109,7 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
     AVIOContext *pb;
     uint8_t *buf;
     unsigned int duration, constant_subblock_duration;
+    unsigned int total_duration = 0;
     unsigned int nb_subblocks;
     unsigned int parameter_id;
     size_t out_param_size;
@@ -147,8 +148,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
         constant_subblock_duration = ffio_read_leb(pb);
         if (constant_subblock_duration == 0)
             nb_subblocks = ffio_read_leb(pb);
-        else
+        else {
             nb_subblocks = duration / constant_subblock_duration;
+            total_duration = duration;
+        }
     } else {
         duration = param->duration;
         constant_subblock_duration = param->constant_subblock_duration;
@@ -172,8 +175,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
         void *subblock = av_iamf_param_definition_get_subblock(out_param, i);
         unsigned int subblock_duration = constant_subblock_duration;
 
-        if (!param_definition->mode && !constant_subblock_duration)
+        if (!param_definition->mode && !constant_subblock_duration) {
             subblock_duration = ffio_read_leb(pb);
+            total_duration += subblock_duration;
+        }
 
         switch (param->type) {
         case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
@@ -235,6 +240,12 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
        av_log(s, level, "Underread in parameter_block_obu. %d bytes left at the end\n", len);
     }
 
+    if (!param_definition->mode && !constant_subblock_duration && total_duration != duration) {
+        av_log(s, AV_LOG_ERROR, "Invalid duration in parameter block\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
     switch (param->type) {
     case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN:
         av_free(c->mix);



More information about the ffmpeg-cvslog mailing list