Browse code

rm: prevent infinite loops for index parsing.

Specifically, prevent jumping back in the file for the next index, since
this can lead to infinite loops where we jump between indexes referring
to each other, and don't read indexes that don't fit in the file.

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org

Ronald S. Bultje authored on 2012/02/23 04:33:24
Showing 1 changed files
... ...
@@ -370,8 +370,19 @@ static int rm_read_index(AVFormatContext *s)
370 370
                 st = s->streams[n];
371 371
                 break;
372 372
             }
373
-        if (n == s->nb_streams)
373
+        if (n == s->nb_streams) {
374
+            av_log(s, AV_LOG_ERROR,
375
+                   "Invalid stream index %d for index at pos %"PRId64"\n",
376
+                   str_id, avio_tell(pb));
374 377
             goto skip;
378
+        } else if ((avio_size(pb) - avio_tell(pb)) / 14 < n_pkts) {
379
+            av_log(s, AV_LOG_ERROR,
380
+                   "Nr. of packets in packet index for stream index %d "
381
+                   "exceeds filesize (%"PRId64" at %"PRId64" = %d)\n",
382
+                   str_id, avio_size(pb), avio_tell(pb),
383
+                   (avio_size(pb) - avio_tell(pb)) / 14);
384
+            goto skip;
385
+        }
375 386
 
376 387
         for (n = 0; n < n_pkts; n++) {
377 388
             avio_skip(pb, 2);
... ...
@@ -383,9 +394,12 @@ static int rm_read_index(AVFormatContext *s)
383 383
         }
384 384
 
385 385
 skip:
386
-        if (next_off && avio_tell(pb) != next_off &&
387
-            avio_seek(pb, next_off, SEEK_SET) < 0)
386
+        if (next_off && avio_tell(pb) < next_off &&
387
+            avio_seek(pb, next_off, SEEK_SET) < 0) {
388
+            av_log(s, AV_LOG_ERROR,
389
+                   "Non-linear index detected, not supported\n");
388 390
             return -1;
391
+        }
389 392
     } while (next_off);
390 393
 
391 394
     return 0;