aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/apv_decode.c
diff options
context:
space:
mode:
authorJames Almer <jamrial@gmail.com>2025-08-10 13:44:31 -0300
committerJames Almer <jamrial@gmail.com>2025-08-12 19:59:21 +0000
commit4b39d776c39f3a049932c8be0d46f48a4a3a0a7c (patch)
treedc4eb5ae84c6f89a51ceaca1e5edea31becf34e7 /libavcodec/apv_decode.c
parent0469d68acb52081ca8385b844b9650398242be0f (diff)
downloadffmpeg-4b39d776c39f3a049932c8be0d46f48a4a3a0a7c.tar.gz
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@gmail.com>
Diffstat (limited to 'libavcodec/apv_decode.c')
-rw-r--r--libavcodec/apv_decode.c49
1 files changed, 45 insertions, 4 deletions
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);