]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/wavdec.c
wavdec: avoid output of arbitrary chars
[ffmpeg] / libavformat / wavdec.c
index 9c4e2dfa148adcc64fec8207e67bff7696b79732..98e97878cb2c7924414d41e1d537cc378796f884 100644 (file)
@@ -57,14 +57,19 @@ typedef struct WAVDemuxContext {
     int smv_cur_pt;
     int smv_given_first;
     int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
+    int rifx; // RIFX: integer byte order for parameters is big endian
 } WAVDemuxContext;
 
 #if CONFIG_WAV_DEMUXER
 
-static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
+static int64_t next_tag(AVIOContext *pb, uint32_t *tag, int big_endian)
 {
     *tag = avio_rl32(pb);
-    return avio_rl32(pb);
+    if (!big_endian) {
+        return avio_rl32(pb);
+    } else {
+        return avio_rb32(pb);
+    }
 }
 
 /* RIFF chunks are always at even offsets relative to where they start. */
@@ -84,7 +89,7 @@ static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1)
     for (;;) {
         if (avio_feof(pb))
             return AVERROR_EOF;
-        size = next_tag(pb, &tag);
+        size = next_tag(pb, &tag, wav->rifx);
         if (tag == tag1)
             break;
         wav_seek_tag(wav, pb, size, SEEK_CUR);
@@ -98,7 +103,7 @@ static int wav_probe(AVProbeData *p)
     if (p->buf_size <= 32)
         return 0;
     if (!memcmp(p->buf + 8, "WAVE", 4)) {
-        if (!memcmp(p->buf, "RIFF", 4))
+        if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))
             /* Since the ACT demuxer has a standard WAV header at the top of
              * its own, the returned score is decreased to avoid a probe
              * conflict between ACT and WAV. */
@@ -121,6 +126,7 @@ static void handle_stream_probing(AVStream *st)
 static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
 {
     AVIOContext *pb = s->pb;
+    WAVDemuxContext *wav = s->priv_data;
     int ret;
 
     /* parse fmt header */
@@ -128,7 +134,7 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
     if (!*st)
         return AVERROR(ENOMEM);
 
-    ret = ff_get_wav_header(pb, (*st)->codec, size);
+    ret = ff_get_wav_header(pb, (*st)->codec, size, wav->rifx);
     if (ret < 0)
         return ret;
     handle_stream_probing(*st);
@@ -242,7 +248,8 @@ static int wav_read_header(AVFormatContext *s)
 {
     int64_t size, av_uninit(data_size);
     int64_t sample_count = 0;
-    int rf64;
+    int rf64 = 0;
+    char start_code[5];
     uint32_t tag;
     AVIOContext *pb      = s->pb;
     AVStream *st         = NULL;
@@ -254,16 +261,31 @@ static int wav_read_header(AVFormatContext *s)
 
     wav->smv_data_ofs = -1;
 
-    /* check RIFF header */
+    /* read chunk ID */
     tag = avio_rl32(pb);
-
-    rf64 = tag == MKTAG('R', 'F', '6', '4');
-    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
+    switch (tag) {
+    case MKTAG('R', 'I', 'F', 'F'):
+        break;
+    case MKTAG('R', 'I', 'F', 'X'):
+        wav->rifx = 1;
+        break;
+    case MKTAG('R', 'F', '6', '4'):
+        rf64 = 1;
+        break;
+    default:
+        av_get_codec_tag_string(start_code, 5, tag);
+        av_log(s, AV_LOG_ERROR, "invalid start code %s in RIFF header\n", start_code);
         return AVERROR_INVALIDDATA;
-    avio_rl32(pb); /* file size */
-    tag = avio_rl32(pb);
-    if (tag != MKTAG('W', 'A', 'V', 'E'))
+    }
+
+    /* read chunk size */
+    avio_rl32(pb);
+
+    /* read format */
+    if (avio_rl32(pb) != MKTAG('W', 'A', 'V', 'E')) {
+        av_log(s, AV_LOG_ERROR, "invalid format in RIFF header\n");
         return AVERROR_INVALIDDATA;
+    }
 
     if (rf64) {
         if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
@@ -288,7 +310,7 @@ static int wav_read_header(AVFormatContext *s)
 
     for (;;) {
         AVStream *vst;
-        size         = next_tag(pb, &tag);
+        size         = next_tag(pb, &tag, wav->rifx);
         next_tag_ofs = avio_tell(pb) + size;
 
         if (avio_feof(pb))
@@ -328,7 +350,7 @@ static int wav_read_header(AVFormatContext *s)
             break;
         case MKTAG('f', 'a', 'c', 't'):
             if (!sample_count)
-                sample_count = avio_rl32(pb);
+                sample_count = (!wav->rifx ? avio_rl32(pb) : avio_rb32(pb));
             break;
         case MKTAG('b', 'e', 'x', 't'):
             if ((ret = wav_parse_bext_tag(s, size)) < 0)
@@ -662,7 +684,7 @@ static int w64_read_header(AVFormatContext *s)
 
         if (!memcmp(guid, ff_w64_guid_fmt, 16)) {
             /* subtract chunk header size - normal wav file doesn't count it */
-            ret = ff_get_wav_header(pb, st->codec, size - 24);
+            ret = ff_get_wav_header(pb, st->codec, size - 24, 0);
             if (ret < 0)
                 return ret;
             avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);