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

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
35#include "thread.h"35#include "thread.h"
36 36
37 37
38typedef 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
38typedef struct APVDecodeContext {48typedef struct APVDecodeContext {
39 CodedBitstreamContext *cbc;49 CodedBitstreamContext *cbc;
40 APVDSPContext dsp;50 APVDSPContext dsp;
@@ -184,7 +194,7 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 143 unmodified lines
184 APVRawFrame *input = data;194 APVRawFrame *input = data;
185 APVDecodeContext *apv = avctx->priv_data;195 APVDecodeContext *apv = avctx->priv_data;
186 const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;196 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;
188 198
189 int tile_index = job / apv_cbc->num_comp;199 int tile_index = job / apv_cbc->num_comp;
190 int comp_index = job % apv_cbc->num_comp;200 int comp_index = job % apv_cbc->num_comp;
@@ -297,12 +307,38 @@ fail: · 106 unmodified lines
297 return err;307 return err;
298}308}
299 309
310static 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
300static int apv_decode(AVCodecContext *avctx, AVFrame *output,336static int apv_decode(AVCodecContext *avctx, AVFrame *output,
301 APVRawFrame *input)337 APVRawFrame *input)
302{338{
303 APVDecodeContext *apv = avctx->priv_data;339 APVDecodeContext *apv = avctx->priv_data;
304 const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;340 const AVPixFmtDescriptor *desc = NULL;
305 const APVDerivedTileInfo *tile_info = &apv_cbc->tile_info;341 APVDerivedTileInfo *tile_info = &apv->tile_info;
306 int err, job_count;342 int err, job_count;
307 343
308 err = apv_decode_check_format(avctx, &input->frame_header);344 err = apv_decode_check_format(avctx, &input->frame_header);
@@ -311,6 +347,9 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 2 unmodified lines
311 return err;347 return err;
312 }348 }
313 349
350 desc = av_pix_fmt_desc_get(avctx->pix_fmt);
351 av_assert0(desc);
352
314 err = ff_thread_get_buffer(avctx, output, 0);353 err = ff_thread_get_buffer(avctx, output, 0);
315 if (err < 0)354 if (err < 0)
316 return err;355 return err;
@@ -318,9 +357,11 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 1 unmodified line
318 apv->output_frame = output;357 apv->output_frame = output;
319 atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);358 atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
320 359
360 apv_derive_tile_info(tile_info, &input->frame_header);
361
321 // Each component within a tile is independent of every other,362 // Each component within a tile is independent of every other,
322 // so we can decode all in parallel.363 // 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;
324 365
325 avctx->execute2(avctx, apv_decode_tile_component,366 avctx->execute2(avctx, apv_decode_tile_component,
326 input, NULL, job_count);367 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
37 }37 }
38}38}
39 39
40static void cbs_apv_derive_tile_info(APVDerivedTileInfo *ti,40static void cbs_apv_derive_tile_info(CodedBitstreamContext *ctx,
41 const APVRawFrameHeader *fh)41 const APVRawFrameHeader *fh)
42{42{
43 CodedBitstreamAPVContext *priv = ctx->priv_data;
43 int frame_width_in_mbs = (fh->frame_info.frame_width + 15) / 16;44 int frame_width_in_mbs = (fh->frame_info.frame_width + 15) / 16;
44 int frame_height_in_mbs = (fh->frame_info.frame_height + 15) / 16;45 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;
46 48
47 start_mb = 0;49 av_assert0(tile_cols <= APV_MAX_TILE_COLS && tile_rows <= APV_MAX_TILE_ROWS);
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;
65 50
66 ti->num_tiles = ti->tile_cols * ti->tile_rows;51 priv->num_tiles = tile_cols * tile_rows;
67}52}
68 53
69 54
libavcodec/cbs_apv.h+1−11
@@ -187,21 +187,11 @@ typedef struct APVRawMetadata { · 186 unmodified lines
187} APVRawMetadata;187} APVRawMetadata;
188 188
189 189
190typedef 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
200typedef struct CodedBitstreamAPVContext {190typedef struct CodedBitstreamAPVContext {
201 int bit_depth;191 int bit_depth;
202 int num_comp;192 int num_comp;
203 193
204 APVDerivedTileInfo tile_info;194 uint16_t num_tiles;
205} CodedBitstreamAPVContext;195} CodedBitstreamAPVContext;
206 196
207#endif /* AVCODEC_CBS_APV_H */197#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
128 128
129 ub(1, tile_size_present_in_fh_flag);129 ub(1, tile_size_present_in_fh_flag);
130 130
131 cbs_apv_derive_tile_info(&priv->tile_info, fh);131 cbs_apv_derive_tile_info(ctx, fh);
132 132
133 if (current->tile_size_present_in_fh_flag) {133 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++) {
135 us(32, tile_size_in_fh[t], 10, MAX_UINT_BITS(32), 1, t);135 us(32, tile_size_in_fh[t], 10, MAX_UINT_BITS(32), 1, t);
136 }136 }
137 }137 }
@@ -262,7 +262,7 @@ static int FUNC(frame)(CodedBitstreamContext *ctx, RWContext *rw, · 124 unmodified lines
262 262
263 CHECK(FUNC(frame_header)(ctx, rw, &current->frame_header));263 CHECK(FUNC(frame_header)(ctx, rw, &current->frame_header));
264 264
265 for (int t = 0; t < priv->tile_info.num_tiles; t++) {265 for (int t = 0; t < priv->num_tiles; t++) {
266 us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t);266 us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t);
267 267
268 CHECK(FUNC(tile)(ctx, rw, &current->tile[t],268 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