]> git.sesse.net Git - ffmpeg/commitdiff
lavf/wavdec: Fix seeking in files with unaligned offsets
authorAlexander Strasser <eclipse7@gmx.net>
Tue, 13 Aug 2013 16:36:21 +0000 (18:36 +0200)
committerAlexander Strasser <eclipse7@gmx.net>
Wed, 14 Aug 2013 20:05:41 +0000 (22:05 +0200)
A file with a prepended ID3 tag of an uneven length was found
in the wild.

Check if the wav data starts at an uneven offset and use that
information to correct the seeking calculation in wav_seek_tag,
which used to only seek to even byte positions.

Regression since ac87eaf856e0fb51917266b899bb15d19b907baf

Signed-off-by: Alexander Strasser <eclipse7@gmx.net>
libavformat/wavdec.c

index adf41ecd89963d31314dee7504b9fa7fe013a924..d5b3b9ef2f331aa6742630b05bcfe260855fe22a 100644 (file)
@@ -54,6 +54,7 @@ typedef struct WAVDemuxContext {
     int spdif;
     int smv_cur_pt;
     int smv_given_first;
+    int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
 } WAVDemuxContext;
 
 #if CONFIG_WAV_DEMUXER
@@ -64,16 +65,16 @@ static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
     return avio_rl32(pb);
 }
 
-/* RIFF chunks are always on a even offset. */
-static int64_t wav_seek_tag(AVIOContext *s, int64_t offset, int whence)
+/* RIFF chunks are always at even offsets relative to where they start. */
+static int64_t wav_seek_tag(WAVDemuxContext * wav, AVIOContext *s, int64_t offset, int whence)
 {
-    offset += offset < INT64_MAX && offset & 1;
+    offset += offset < INT64_MAX && offset + wav->unaligned & 1;
 
     return avio_seek(s, offset, whence);
 }
 
 /* return the size of the found tag */
-static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
+static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1)
 {
     unsigned int tag;
     int64_t size;
@@ -84,7 +85,7 @@ static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
         size = next_tag(pb, &tag);
         if (tag == tag1)
             break;
-        wav_seek_tag(pb, size, SEEK_CUR);
+        wav_seek_tag(wav, pb, size, SEEK_CUR);
     }
     return size;
 }
@@ -247,6 +248,8 @@ static int wav_read_header(AVFormatContext *s)
     int ret, got_fmt = 0;
     int64_t next_tag_ofs, data_ofs = -1;
 
+    wav->unaligned = avio_tell(s->pb) & 1;
+
     wav->smv_data_ofs = -1;
 
     /* check RIFF header */
@@ -383,7 +386,7 @@ static int wav_read_header(AVFormatContext *s)
 
         /* seek to next tag unless we know that we'll run into EOF */
         if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
-            wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) {
+            wav_seek_tag(wav, pb, next_tag_ofs, SEEK_SET) < 0) {
             break;
         }
     }
@@ -511,7 +514,7 @@ smv_out:
         if (CONFIG_W64_DEMUXER && wav->w64)
             left = find_guid(s->pb, ff_w64_guid_data) - 24;
         else
-            left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
+            left = find_tag(wav, s->pb, MKTAG('d', 'a', 't', 'a'));
         if (left < 0) {
             wav->audio_eof = 1;
             if (wav->smv_data_ofs > 0 && !wav->smv_eof)