Browse code

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 a105f52855d08e4ab1ed7306da8e32fc90d6d647)

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

Michael Niedermayer authored on 2015/11/15 05:11:52
Showing 1 changed files
... ...
@@ -381,14 +381,19 @@ static void guess_mv(ERContext *s)
381 381
 #define MV_UNCHANGED 1
382 382
     const int mb_stride = s->mb_stride;
383 383
     const int mb_width  = s->mb_width;
384
-    const int mb_height = s->mb_height;
384
+    int mb_height = s->mb_height;
385 385
     int i, depth, num_avail;
386 386
     int mb_x, mb_y, mot_step, mot_stride;
387 387
 
388
+    if (s->last_pic.f && s->last_pic.f->data[0])
389
+        mb_height = FFMIN(mb_height, (s->last_pic.f->height+15)>>4);
390
+    if (s->next_pic.f && s->next_pic.f->data[0])
391
+        mb_height = FFMIN(mb_height, (s->next_pic.f->height+15)>>4);
392
+
388 393
     set_mv_strides(s, &mot_step, &mot_stride);
389 394
 
390 395
     num_avail = 0;
391
-    for (i = 0; i < s->mb_num; i++) {
396
+    for (i = 0; i < mb_width * mb_height; i++) {
392 397
         const int mb_xy = s->mb_index2xy[i];
393 398
         int f = 0;
394 399
         int error = s->error_status_table[mb_xy];
... ...
@@ -413,7 +418,7 @@ static void guess_mv(ERContext *s)
413 413
 
414 414
     if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
415 415
         num_avail <= mb_width / 2) {
416
-        for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
416
+        for (mb_y = 0; mb_y < mb_height; mb_y++) {
417 417
             for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
418 418
                 const int mb_xy = mb_x + mb_y * s->mb_stride;
419 419
                 int mv_dir = (s->last_pic.f && s->last_pic.f->data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD;
... ...
@@ -442,7 +447,7 @@ static void guess_mv(ERContext *s)
442 442
             int score_sum = 0;
443 443
 
444 444
             changed = 0;
445
-            for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
445
+            for (mb_y = 0; mb_y < mb_height; mb_y++) {
446 446
                 for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
447 447
                     const int mb_xy        = mb_x + mb_y * s->mb_stride;
448 448
                     int mv_predictor[8][2] = { { 0 } };
... ...
@@ -675,7 +680,7 @@ skip_last_mv:
675 675
         if (none_left)
676 676
             return;
677 677
 
678
-        for (i = 0; i < s->mb_num; i++) {
678
+        for (i = 0; i < mb_width * mb_height; i++) {
679 679
             int mb_xy = s->mb_index2xy[i];
680 680
             if (fixed[mb_xy])
681 681
                 fixed[mb_xy] = MV_FROZEN;