mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec/error_resilience: avoid accessing previous or next frames tables beyond height
The height of tables can be rounded up for MBAFF but this does not imply that is also true
for the previous frames
Fixes out of array reads
Fixes: c106b36fa36db8ff8f3ed0c82be7bea2/asan_heap-oob_32699f0_6321_467b9a1d7e03d7cfd310b7e65dc53bcc.mov
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit a105f52855
)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
99e080ec38
commit
3879202d68
|
@ -377,14 +377,19 @@ static void guess_mv(ERContext *s)
|
||||||
#define MV_UNCHANGED 1
|
#define MV_UNCHANGED 1
|
||||||
const int mb_stride = s->mb_stride;
|
const int mb_stride = s->mb_stride;
|
||||||
const int mb_width = s->mb_width;
|
const int mb_width = s->mb_width;
|
||||||
const int mb_height = s->mb_height;
|
int mb_height = s->mb_height;
|
||||||
int i, depth, num_avail;
|
int i, depth, num_avail;
|
||||||
int mb_x, mb_y, mot_step, mot_stride;
|
int mb_x, mb_y, mot_step, mot_stride;
|
||||||
|
|
||||||
|
if (s->last_pic.f && s->last_pic.f->data[0])
|
||||||
|
mb_height = FFMIN(mb_height, (s->last_pic.f->height+15)>>4);
|
||||||
|
if (s->next_pic.f && s->next_pic.f->data[0])
|
||||||
|
mb_height = FFMIN(mb_height, (s->next_pic.f->height+15)>>4);
|
||||||
|
|
||||||
set_mv_strides(s, &mot_step, &mot_stride);
|
set_mv_strides(s, &mot_step, &mot_stride);
|
||||||
|
|
||||||
num_avail = 0;
|
num_avail = 0;
|
||||||
for (i = 0; i < s->mb_num; i++) {
|
for (i = 0; i < mb_width * mb_height; i++) {
|
||||||
const int mb_xy = s->mb_index2xy[i];
|
const int mb_xy = s->mb_index2xy[i];
|
||||||
int f = 0;
|
int f = 0;
|
||||||
int error = s->error_status_table[mb_xy];
|
int error = s->error_status_table[mb_xy];
|
||||||
|
@ -409,7 +414,7 @@ static void guess_mv(ERContext *s)
|
||||||
|
|
||||||
if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
|
if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
|
||||||
num_avail <= mb_width / 2) {
|
num_avail <= mb_width / 2) {
|
||||||
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
|
for (mb_y = 0; mb_y < mb_height; mb_y++) {
|
||||||
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
|
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
|
||||||
const int mb_xy = mb_x + mb_y * s->mb_stride;
|
const int mb_xy = mb_x + mb_y * s->mb_stride;
|
||||||
int mv_dir = (s->last_pic.f && s->last_pic.f->data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
|
int mv_dir = (s->last_pic.f && s->last_pic.f->data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
|
||||||
|
@ -438,7 +443,7 @@ static void guess_mv(ERContext *s)
|
||||||
int score_sum = 0;
|
int score_sum = 0;
|
||||||
|
|
||||||
changed = 0;
|
changed = 0;
|
||||||
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
|
for (mb_y = 0; mb_y < mb_height; mb_y++) {
|
||||||
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
|
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
|
||||||
const int mb_xy = mb_x + mb_y * s->mb_stride;
|
const int mb_xy = mb_x + mb_y * s->mb_stride;
|
||||||
int mv_predictor[8][2] = { { 0 } };
|
int mv_predictor[8][2] = { { 0 } };
|
||||||
|
@ -671,7 +676,7 @@ skip_last_mv:
|
||||||
if (none_left)
|
if (none_left)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < s->mb_num; i++) {
|
for (i = 0; i < mb_width * mb_height; i++) {
|
||||||
int mb_xy = s->mb_index2xy[i];
|
int mb_xy = s->mb_index2xy[i];
|
||||||
if (fixed[mb_xy])
|
if (fixed[mb_xy])
|
||||||
fixed[mb_xy] = MV_FROZEN;
|
fixed[mb_xy] = MV_FROZEN;
|
||||||
|
|
Loading…
Reference in New Issue