Halt tile component decoding at the first entropy error (this will be a desync and is not recoverable). If any tile components contain errors then discard the frame unless the output-corrupt flag is set. Also fixes CID 1646764, which is the error case where the tile component is too large for get_bits to handle.
Unified · Split
| @@ -16,6 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | 17 | */ |
| 18 | 18 | |
| 19 | +#include <stdatomic.h> | |
| 20 | + | |
| 19 | 21 | #include "libavutil/mastering_display_metadata.h" |
| 20 | 22 | #include "libavutil/mem_internal.h" |
| 21 | 23 | #include "libavutil/pixdesc.h" |
| @@ -41,6 +43,7 @@ typedef struct APVDecodeContext { · 19 unmodified lines | ||
| 41 | 43 | APVDerivedTileInfo tile_info; |
| 42 | 44 | |
| 43 | 45 | AVFrame *output_frame; |
| 46 | + atomic_int tile_errors; | |
| 44 | 47 | |
| 45 | 48 | uint8_t warned_additional_frames; |
| 46 | 49 | uint8_t warned_unknown_pbu_types; |
| @@ -129,6 +132,8 @@ static av_cold int apv_decode_init(AVCodecContext *avctx) · 82 unmodified lines | ||
| 129 | 132 | |
| 130 | 133 | ff_apv_dsp_init(&apv->dsp); |
| 131 | 134 | |
| 135 | + atomic_init(&apv->tile_errors, 0); | |
| 136 | + | |
| 132 | 137 | return 0; |
| 133 | 138 | } |
| 134 | 139 | |
| @@ -158,7 +163,7 @@ static int apv_decode_block(AVCodecContext *avctx, · 23 unmodified lines | ||
| 158 | 163 | |
| 159 | 164 | err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state); |
| 160 | 165 | if (err < 0) |
| 161 | − return 0; | |
| 166 | + return err; | |
| 162 | 167 | |
| 163 | 168 | apv->dsp.decode_transquant(output, pitch, |
| 164 | 169 | coeff, qmatrix, |
| @@ -215,8 +220,12 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 50 unmodified lines | ||
| 215 | 220 | .prev_1st_ac_level = 0, |
| 216 | 221 | }; |
| 217 | 222 | |
| 218 | − init_get_bits8(&gbc, tile->tile_data[comp_index], | |
| 219 | − tile->tile_header.tile_data_size[comp_index]); | |
| 223 | + int err; | |
| 224 | + | |
| 225 | + err = init_get_bits8(&gbc, tile->tile_data[comp_index], | |
| 226 | + tile->tile_header.tile_data_size[comp_index]); | |
| 227 | + if (err < 0) | |
| 228 | + goto fail; | |
| 220 | 229 | |
| 221 | 230 | // Combine the bitstream quantisation matrix with the qp scaling |
| 222 | 231 | // in advance. (Including qp_shift as well would overflow 16 bits.) |
| @@ -251,12 +260,17 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 28 unmodified lines | ||
| 251 | 260 | uint8_t *block_start = apv->output_frame->data[comp_index] + |
| 252 | 261 | frame_y * frame_pitch + 2 * frame_x; |
| 253 | 262 | |
| 254 | − apv_decode_block(avctx, | |
| 255 | − block_start, frame_pitch, | |
| 256 | − &gbc, &entropy_state, | |
| 257 | − bit_depth, | |
| 258 | − qp_shift, | |
| 259 | − qmatrix_scaled); | |
| 263 | + err = apv_decode_block(avctx, | |
| 264 | + block_start, frame_pitch, | |
| 265 | + &gbc, &entropy_state, | |
| 266 | + bit_depth, | |
| 267 | + qp_shift, | |
| 268 | + qmatrix_scaled); | |
| 269 | + if (err < 0) { | |
| 270 | + // Error in block decode means entropy desync, | |
| 271 | + // so this is not recoverable. | |
| 272 | + goto fail; | |
| 273 | + } | |
| 260 | 274 | } |
| 261 | 275 | } |
| 262 | 276 | } |
| @@ -268,6 +282,13 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data, · 5 unmodified lines | ||
| 268 | 282 | tile_start_x, tile_start_y); |
| 269 | 283 | |
| 270 | 284 | return 0; |
| 285 | + | |
| 286 | +fail: | |
| 287 | + av_log(avctx, AV_LOG_VERBOSE, | |
| 288 | + "Decode error in tile %d component %d.\n", | |
| 289 | + tile_index, comp_index); | |
| 290 | + atomic_fetch_add_explicit(&apv->tile_errors, 1, memory_order_relaxed); | |
| 291 | + return err; | |
| 271 | 292 | } |
| 272 | 293 | |
| 273 | 294 | static int apv_decode(AVCodecContext *avctx, AVFrame *output, |
| @@ -289,6 +310,7 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 15 unmodified lines | ||
| 289 | 310 | return err; |
| 290 | 311 | |
| 291 | 312 | apv->output_frame = output; |
| 313 | + atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed); | |
| 292 | 314 | |
| 293 | 315 | // Each component within a tile is independent of every other, |
| 294 | 316 | // so we can decode all in parallel. |
| @@ -297,6 +319,18 @@ static int apv_decode(AVCodecContext *avctx, AVFrame *output, · 2 unmodified lines | ||
| 297 | 319 | avctx->execute2(avctx, apv_decode_tile_component, |
| 298 | 320 | input, NULL, job_count); |
| 299 | 321 | |
| 322 | + err = atomic_load_explicit(&apv->tile_errors, memory_order_relaxed); | |
| 323 | + if (err > 0) { | |
| 324 | + av_log(avctx, AV_LOG_ERROR, | |
| 325 | + "Decode errors in %d tile components.\n", err); | |
| 326 | + if (avctx->flags & AV_CODEC_FLAG_OUTPUT_CORRUPT) { | |
| 327 | + // Output the frame anyway. | |
| 328 | + output->flags |= AV_FRAME_FLAG_CORRUPT; | |
| 329 | + } else { | |
| 330 | + return AVERROR_INVALIDDATA; | |
| 331 | + } | |
| 332 | + } | |
| 333 | + | |
| 300 | 334 | return 0; |
| 301 | 335 | } |
| 302 | 336 | |