[FFmpeg-cvslog] [ffmpeg] branch release/8.0 updated. 13b161cd24 avcodec/cbs_apv: store derived tile information in a per frame basis

ffmpeg-git at ffmpeg.org ffmpeg-git at ffmpeg.org
Wed Aug 13 01:14:21 EEST 2025


The branch, release/8.0 has been updated
       via  13b161cd24bc703bf37a835af70d366229d75e12 (commit)
       via  7c92f740eea4cd506763fb6d78268eb41175fcd4 (commit)
      from  057b94649f780b51d20114896edc0cba49f8f828 (commit)


- Log -----------------------------------------------------------------
commit 13b161cd24bc703bf37a835af70d366229d75e12
Author:     James Almer <jamrial at gmail.com>
AuthorDate: Sun Aug 10 13:44:31 2025 -0300
Commit:     James Almer <jamrial at gmail.com>
CommitDate: Tue Aug 12 19:13:06 2025 -0300

    avcodec/cbs_apv: store derived tile information in a per frame basis
    
    If a single fragment contains more than one frame unit, the tile information stored
    in the private context will only correspond to one of them.
    
    Fixes: crash (out of array access)
    Fixes: 435489659/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-6194885205229568
    
    Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
    Signed-off-by: James Almer <jamrial at gmail.com>
    (cherry picked from commit 4b39d776c39f3a049932c8be0d46f48a4a3a0a7c)

diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c
index 330d4980c0..dd8a07e24f 100644
--- a/libavcodec/apv_decode.c
+++ b/libavcodec/apv_decode.c
@@ -35,6 +35,16 @@
 #include "thread.h"
 
 
+typedef struct APVDerivedTileInfo {
+    uint8_t  tile_cols;
+    uint8_t  tile_rows;
+    uint16_t num_tiles;
+    // The spec uses an extra element on the end of these arrays
+    // not corresponding to any tile.
+    uint16_t col_starts[APV_MAX_TILE_COLS + 1];
+    uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
+} APVDerivedTileInfo;
+
 typedef struct APVDecodeContext {
     CodedBitstreamContext *cbc;
     APVDSPContext dsp;
@@ -184,7 +194,7 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data,
     APVRawFrame                      *input = data;
     APVDecodeContext                   *apv = avctx->priv_data;
     const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
-    const APVDerivedTileInfo     *tile_info = &apv_cbc->tile_info;
+    const APVDerivedTileInfo     *tile_info = &apv->tile_info;
 
     int tile_index = job / apv_cbc->num_comp;
     int comp_index = job % apv_cbc->num_comp;
@@ -297,12 +307,38 @@ fail:
     return err;
 }
 
+static void apv_derive_tile_info(APVDerivedTileInfo *ti,
+                                 const APVRawFrameHeader *fh)
+{
+    int frame_width_in_mbs  = (fh->frame_info.frame_width  + (APV_MB_WIDTH  - 1)) >> 4;
+    int frame_height_in_mbs = (fh->frame_info.frame_height + (APV_MB_HEIGHT - 1)) >> 4;
+    int start_mb, i;
+
+    start_mb = 0;
+    for (i = 0; start_mb < frame_width_in_mbs; i++) {
+        ti->col_starts[i] = start_mb * APV_MB_WIDTH;
+        start_mb += fh->tile_info.tile_width_in_mbs;
+    }
+    ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
+    ti->tile_cols = i;
+
+    start_mb = 0;
+    for (i = 0; start_mb < frame_height_in_mbs; i++) {
+        ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
+        start_mb += fh->tile_info.tile_height_in_mbs;
+    }
+    ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
+    ti->tile_rows = i;
+
+    ti->num_tiles = ti->tile_cols * ti->tile_rows;
+}
+
 static int apv_decode(AVCodecContext *avctx, AVFrame *output,
                       APVRawFrame *input)
 {
     APVDecodeContext                   *apv = avctx->priv_data;
-    const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
-    const APVDerivedTileInfo     *tile_info = &apv_cbc->tile_info;
+    const AVPixFmtDescriptor          *desc = NULL;
+    APVDerivedTileInfo           *tile_info = &apv->tile_info;
     int err, job_count;
 
     err = apv_decode_check_format(avctx, &input->frame_header);
@@ -311,6 +347,9 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output,
         return err;
     }
 
+    desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+    av_assert0(desc);
+
     err = ff_thread_get_buffer(avctx, output, 0);
     if (err < 0)
         return err;
@@ -318,9 +357,11 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output,
     apv->output_frame = output;
     atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
 
+    apv_derive_tile_info(tile_info, &input->frame_header);
+
     // Each component within a tile is independent of every other,
     // so we can decode all in parallel.
-    job_count = tile_info->num_tiles * apv_cbc->num_comp;
+    job_count = tile_info->num_tiles * desc->nb_components;
 
     avctx->execute2(avctx, apv_decode_tile_component,
                     input, NULL, job_count);
diff --git a/libavcodec/cbs_apv.c b/libavcodec/cbs_apv.c
index 5239cd1269..fdc9042939 100644
--- a/libavcodec/cbs_apv.c
+++ b/libavcodec/cbs_apv.c
@@ -37,33 +37,18 @@ static int cbs_apv_get_num_comp(const APVRawFrameHeader *fh)
     }
 }
 
-static void cbs_apv_derive_tile_info(APVDerivedTileInfo *ti,
+static void cbs_apv_derive_tile_info(CodedBitstreamContext *ctx,
                                      const APVRawFrameHeader *fh)
 {
+    CodedBitstreamAPVContext *priv = ctx->priv_data;
     int frame_width_in_mbs   = (fh->frame_info.frame_width  + 15) / 16;
     int frame_height_in_mbs  = (fh->frame_info.frame_height + 15) / 16;
-    int start_mb, i;
+    int tile_cols = (frame_width_in_mbs  + fh->tile_info.tile_width_in_mbs - 1)  / fh->tile_info.tile_width_in_mbs;
+    int tile_rows = (frame_height_in_mbs + fh->tile_info.tile_height_in_mbs - 1) / fh->tile_info.tile_height_in_mbs;
 
-    start_mb = 0;
-    for (i = 0; start_mb < frame_width_in_mbs; i++) {
-        ti->col_starts[i] = start_mb * APV_MB_WIDTH;
-        start_mb += fh->tile_info.tile_width_in_mbs;
-    }
-    av_assert0(i <= APV_MAX_TILE_COLS);
-    ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
-    ti->tile_cols = i;
-
-    start_mb = 0;
-    for (i = 0; start_mb < frame_height_in_mbs; i++) {
-        av_assert0(i < APV_MAX_TILE_ROWS);
-        ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
-        start_mb += fh->tile_info.tile_height_in_mbs;
-    }
-    av_assert0(i <= APV_MAX_TILE_ROWS);
-    ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
-    ti->tile_rows = i;
+    av_assert0(tile_cols <= APV_MAX_TILE_COLS && tile_rows <= APV_MAX_TILE_ROWS);
 
-    ti->num_tiles = ti->tile_cols * ti->tile_rows;
+    priv->num_tiles = tile_cols * tile_rows;
 }
 
 
diff --git a/libavcodec/cbs_apv.h b/libavcodec/cbs_apv.h
index cbaeb45acb..d91372e644 100644
--- a/libavcodec/cbs_apv.h
+++ b/libavcodec/cbs_apv.h
@@ -187,21 +187,11 @@ typedef struct APVRawMetadata {
 } APVRawMetadata;
 
 
-typedef struct APVDerivedTileInfo {
-    uint8_t  tile_cols;
-    uint8_t  tile_rows;
-    uint16_t num_tiles;
-    // The spec uses an extra element on the end of these arrays
-    // not corresponding to any tile.
-    uint16_t col_starts[APV_MAX_TILE_COLS + 1];
-    uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
-} APVDerivedTileInfo;
-
 typedef struct CodedBitstreamAPVContext {
     int bit_depth;
     int num_comp;
 
-    APVDerivedTileInfo tile_info;
+    uint16_t num_tiles;
 } CodedBitstreamAPVContext;
 
 #endif /* AVCODEC_CBS_APV_H */
diff --git a/libavcodec/cbs_apv_syntax_template.c b/libavcodec/cbs_apv_syntax_template.c
index b84565b107..621595ffbf 100644
--- a/libavcodec/cbs_apv_syntax_template.c
+++ b/libavcodec/cbs_apv_syntax_template.c
@@ -128,10 +128,10 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw,
 
     ub(1, tile_size_present_in_fh_flag);
 
-    cbs_apv_derive_tile_info(&priv->tile_info, fh);
+    cbs_apv_derive_tile_info(ctx, fh);
 
     if (current->tile_size_present_in_fh_flag) {
-        for (int t = 0; t < priv->tile_info.num_tiles; t++) {
+        for (int t = 0; t < priv->num_tiles; t++) {
             us(32, tile_size_in_fh[t], 10, MAX_UINT_BITS(32), 1, t);
         }
     }
@@ -262,7 +262,7 @@ static int FUNC(frame)(CodedBitstreamContext *ctx, RWContext *rw,
 
     CHECK(FUNC(frame_header)(ctx, rw, &current->frame_header));
 
-    for (int t = 0; t < priv->tile_info.num_tiles; t++) {
+    for (int t = 0; t < priv->num_tiles; t++) {
         us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t);
 
         CHECK(FUNC(tile)(ctx, rw, &current->tile[t],

commit 7c92f740eea4cd506763fb6d78268eb41175fcd4
Author:     Michael Niedermayer <michael at niedermayer.cc>
AuthorDate: Fri Aug 8 22:37:47 2025 +0200
Commit:     James Almer <jamrial at gmail.com>
CommitDate: Tue Aug 12 19:13:06 2025 -0300

    avcodec/apv_decode: make apv_format_table consistent with the code and check it
    
    Fixes: writing in a null pointer
    Fixes: 435278398/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-4566392923029504
    
    Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
    Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
    (cherry picked from commit cfce5955725c949b363eb2765b6a5891890eca72)

diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c
index eb47298e2e..330d4980c0 100644
--- a/libavcodec/apv_decode.c
+++ b/libavcodec/apv_decode.c
@@ -52,9 +52,9 @@ typedef struct APVDecodeContext {
 static const enum AVPixelFormat apv_format_table[5][5] = {
     { AV_PIX_FMT_GRAY8,    AV_PIX_FMT_GRAY10,     AV_PIX_FMT_GRAY12,     AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16 },
     { 0 }, // 4:2:0 is not valid.
-    { AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV422P10,  AV_PIX_FMT_YUV422P12,  AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV422P16 },
-    { AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV444P10,  AV_PIX_FMT_YUV444P12,  AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUV444P16 },
-    { AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_YUVA444P16 },
+    { AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV422P10,  AV_PIX_FMT_YUV422P12,  AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16 },
+    { AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV444P10,  AV_PIX_FMT_YUV444P12,  AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16 },
+    { AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, 0                   ,AV_PIX_FMT_YUVA444P16 },
 };
 
 static APVVLCLUT decode_lut;
@@ -75,6 +75,11 @@ static int apv_decode_check_format(AVCodecContext *avctx,
     avctx->pix_fmt =
         apv_format_table[header->frame_info.chroma_format_idc][bit_depth - 4 >> 2];
 
+    if (!avctx->pix_fmt) {
+        avpriv_request_sample(avctx, "YUVA444P14");
+        return AVERROR_PATCHWELCOME;
+    }
+
     err = ff_set_dimensions(avctx,
                             FFALIGN(header->frame_info.frame_width,  16),
                             FFALIGN(header->frame_info.frame_height, 16));

-----------------------------------------------------------------------

Summary of changes:
 libavcodec/apv_decode.c              | 60 +++++++++++++++++++++++++++++++-----
 libavcodec/cbs_apv.c                 | 27 ++++------------
 libavcodec/cbs_apv.h                 | 12 +-------
 libavcodec/cbs_apv_syntax_template.c |  6 ++--
 4 files changed, 63 insertions(+), 42 deletions(-)


hooks/post-receive
-- 



More information about the ffmpeg-cvslog mailing list