History

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

James Almer committed 1 year ago

Commit 13b161c1 parent 7c92f744 files · +55 −39Browse files

Showing the changes to libavcodec (4 of 4 files). Show all

Unified · Split

4 files
  1. libavcodec/apv_decode.c +45 −4
  2. libavcodec/cbs_apv.c +6 −21
  3. libavcodec/cbs_apv.h +1 −11
  4. libavcodec/cbs_apv_syntax_template.c +3 −3
libavcodec/apv_decode.c+45−4
@@ -35,6 +35,16 @@ · 34 unmodified lines
3535 #include "thread.h"
3636
3737
38+typedef struct APVDerivedTileInfo {
39+ uint8_t tile_cols;
40+ uint8_t tile_rows;
41+ uint16_t num_tiles;
42+ // The spec uses an extra element on the end of these arrays
43+ // not corresponding to any tile.
44+ uint16_t col_starts[APV_MAX_TILE_COLS + 1];
45+ uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
46+} APVDerivedTileInfo;
47+
3848 typedef struct APVDecodeContext {
3949 CodedBitstreamContext *cbc;
4050 APVDSPContext dsp;
@@ -184,7 +194,7 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 143 unmodified lines
184194 APVRawFrame *input = data;
185195 APVDecodeContext *apv = avctx->priv_data;
186196 const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
187− const APVDerivedTileInfo *tile_info = &apv_cbc->tile_info;
197+ const APVDerivedTileInfo *tile_info = &apv->tile_info;
188198
189199 int tile_index = job / apv_cbc->num_comp;
190200 int comp_index = job % apv_cbc->num_comp;
@@ -297,12 +307,38 @@ fail: · 106 unmodified lines
297307 return err;
298308 }
299309
310+static void apv_derive_tile_info(APVDerivedTileInfo *ti,
311+ const APVRawFrameHeader *fh)
312+{
313+ int frame_width_in_mbs = (fh->frame_info.frame_width + (APV_MB_WIDTH - 1)) >> 4;
314+ int frame_height_in_mbs = (fh->frame_info.frame_height + (APV_MB_HEIGHT - 1)) >> 4;
315+ int start_mb, i;
316+
317+ start_mb = 0;
318+ for (i = 0; start_mb < frame_width_in_mbs; i++) {
319+ ti->col_starts[i] = start_mb * APV_MB_WIDTH;
320+ start_mb += fh->tile_info.tile_width_in_mbs;
321+ }
322+ ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
323+ ti->tile_cols = i;
324+
325+ start_mb = 0;
326+ for (i = 0; start_mb < frame_height_in_mbs; i++) {
327+ ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
328+ start_mb += fh->tile_info.tile_height_in_mbs;
329+ }
330+ ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
331+ ti->tile_rows = i;
332+
333+ ti->num_tiles = ti->tile_cols * ti->tile_rows;
334+}
335+
300336 static int apv_decode(AVCodecContext *avctx, AVFrame *output,
301337 APVRawFrame *input)
302338 {
303339 APVDecodeContext *apv = avctx->priv_data;
304− const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
305− const APVDerivedTileInfo *tile_info = &apv_cbc->tile_info;
340+ const AVPixFmtDescriptor *desc = NULL;
341+ APVDerivedTileInfo *tile_info = &apv->tile_info;
306342 int err, job_count;
307343
308344 err = apv_decode_check_format(avctx, &input->frame_header);
@@ -311,6 +347,9 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 2 unmodified lines
311347 return err;
312348 }
313349
350+ desc = av_pix_fmt_desc_get(avctx->pix_fmt);
351+ av_assert0(desc);
352+
314353 err = ff_thread_get_buffer(avctx, output, 0);
315354 if (err < 0)
316355 return err;
@@ -318,9 +357,11 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 1 unmodified line
318357 apv->output_frame = output;
319358 atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
320359
360+ apv_derive_tile_info(tile_info, &input->frame_header);
361+
321362 // Each component within a tile is independent of every other,
322363 // so we can decode all in parallel.
323− job_count = tile_info->num_tiles * apv_cbc->num_comp;
364+ job_count = tile_info->num_tiles * desc->nb_components;
324365
325366 avctx->execute2(avctx, apv_decode_tile_component,
326367 input, NULL, job_count);
libavcodec/cbs_apv.c+6−21
@@ -37,33 +37,18 @@ static int cbs_apv_get_num_comp(const APVRawFrameHeader *fh) · 36 unmodified lines
3737 }
3838 }
3939
40−static void cbs_apv_derive_tile_info(APVDerivedTileInfo *ti,
40+static void cbs_apv_derive_tile_info(CodedBitstreamContext *ctx,
4141 const APVRawFrameHeader *fh)
4242 {
43+ CodedBitstreamAPVContext *priv = ctx->priv_data;
4344 int frame_width_in_mbs = (fh->frame_info.frame_width + 15) / 16;
4445 int frame_height_in_mbs = (fh->frame_info.frame_height + 15) / 16;
45− int start_mb, i;
46+ int tile_cols = (frame_width_in_mbs + fh->tile_info.tile_width_in_mbs - 1) / fh->tile_info.tile_width_in_mbs;
47+ int tile_rows = (frame_height_in_mbs + fh->tile_info.tile_height_in_mbs - 1) / fh->tile_info.tile_height_in_mbs;
4648
47− start_mb = 0;
48− for (i = 0; start_mb < frame_width_in_mbs; i++) {
49− ti->col_starts[i] = start_mb * APV_MB_WIDTH;
50− start_mb += fh->tile_info.tile_width_in_mbs;
51− }
52− av_assert0(i <= APV_MAX_TILE_COLS);
53− ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
54− ti->tile_cols = i;
55−
56− start_mb = 0;
57− for (i = 0; start_mb < frame_height_in_mbs; i++) {
58− av_assert0(i < APV_MAX_TILE_ROWS);
59− ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
60− start_mb += fh->tile_info.tile_height_in_mbs;
61− }
62− av_assert0(i <= APV_MAX_TILE_ROWS);
63− ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
64− ti->tile_rows = i;
49+ av_assert0(tile_cols <= APV_MAX_TILE_COLS && tile_rows <= APV_MAX_TILE_ROWS);
6550
66− ti->num_tiles = ti->tile_cols * ti->tile_rows;
51+ priv->num_tiles = tile_cols * tile_rows;
6752 }
6853
6954
libavcodec/cbs_apv.h+1−11
@@ -187,21 +187,11 @@ typedef struct APVRawMetadata { · 186 unmodified lines
187187 } APVRawMetadata;
188188
189189
190−typedef struct APVDerivedTileInfo {
191− uint8_t tile_cols;
192− uint8_t tile_rows;
193− uint16_t num_tiles;
194− // The spec uses an extra element on the end of these arrays
195− // not corresponding to any tile.
196− uint16_t col_starts[APV_MAX_TILE_COLS + 1];
197− uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
198−} APVDerivedTileInfo;
199−
200190 typedef struct CodedBitstreamAPVContext {
201191 int bit_depth;
202192 int num_comp;
203193
204− APVDerivedTileInfo tile_info;
194+ uint16_t num_tiles;
205195 } CodedBitstreamAPVContext;
206196
207197 #endif /* AVCODEC_CBS_APV_H */
libavcodec/cbs_apv_syntax_template.c+3−3
@@ -128,10 +128,10 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, · 127 unmodified lines
128128
129129 ub(1, tile_size_present_in_fh_flag);
130130
131− cbs_apv_derive_tile_info(&priv->tile_info, fh);
131+ cbs_apv_derive_tile_info(ctx, fh);
132132
133133 if (current->tile_size_present_in_fh_flag) {
134− for (int t = 0; t < priv->tile_info.num_tiles; t++) {
134+ for (int t = 0; t < priv->num_tiles; t++) {
135135 us(32, tile_size_in_fh[t], 10, MAX_UINT_BITS(32), 1, t);
136136 }
137137 }
@@ -262,7 +262,7 @@ static int FUNC(frame)(CodedBitstreamContext *ctx, RWContext *rw, · 124 unmodified lines
262262
263263 CHECK(FUNC(frame_header)(ctx, rw, &current->frame_header));
264264
265− for (int t = 0; t < priv->tile_info.num_tiles; t++) {
265+ for (int t = 0; t < priv->num_tiles; t++) {
266266 us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t);
267267
268268 CHECK(FUNC(tile)(ctx, rw, &current->tile[t],

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t