Merge commit '5c54fc6195e52c329b88cf5a56d18628f0ee0029' into release/1.1
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 27 Aug 2013 13:37:41 +0000 (15:37 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 27 Aug 2013 13:42:14 +0000 (15:42 +0200)
* commit '5c54fc6195e52c329b88cf5a56d18628f0ee0029':
  Prepare for 9.8 RELEASE
  update Changelog
  smacker: check frame size validity
  smacker: pad the extradata allocation
  smacker: check the return value of smacker_decode_tree
  smacker: fix an off by one in huff.length computation
  4xm: do not overread the prestream buffer
  4xm: validate the buffer size before parsing it
  4xm: reject frames not compatible with the declared version
  4xm: drop pointless assert
  4xm: forward errors from decode_p_block
  4xm: fold last_picture lazy allocation in decode_p_frame
  4xm: do not overread while parsing header
  4xm: refactor fourxm_read_header
  4xm: K&R formatting cosmetics
  4xm: use the correct logging context

Conflicts:
Changelog
RELEASE
libavcodec/4xm.c
libavcodec/smacker.c
libavformat/4xm.c
libavformat/smacker.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Changelog
libavcodec/4xm.c
libavcodec/smacker.c
libavformat/4xm.c
libavformat/smacker.c

diff --cc Changelog
+++ b/Changelog
@@@ -1,7 -1,30 +1,28 @@@
  Entries are sorted chronologically from oldest to youngest within each release,
  releases are sorted from youngest to oldest.
  
 -version 9.7:
 +version <next>:
+ Most of the following fixes resulted from test samples that the Google
+ Security Team has kindly made available to us:
+ - 4xm: fix several programming errors to avoid crashes, etc.
+ - apetag: use int64_t for filesize
+ - jpegls: Fix invalid writes to memory
+ - ljpeg: use the correct number of components in YUV
+ - mjpeg: Validate sampling factors
+ - mjpegdec: properly report unsupported disabled features
+ - mjpegdec: validate parameters in mjpeg_decode_scan_progressive_ac
+ - mpegvideo: allocate sufficiently large scratch buffer for interlaced vid
+ - pixdesc: mark gray8 as pseudopal
+ - smacker: fix several programming errors to avoid crashes, etc.
+ - tiff: do not overread the source buffer
+ - vmd: drop incomplete chunks and spurious samples
+ - vmdav: convert to bytestream2 to avoid invalid reads and writes
+ - wavpack: check packet size early
+ - wavpack: use bytestream2 in wavpack_decode_block
+ - wavpack: validate samples size parsed in wavpack_decode_block
 -
 -version 9.6:
  - aac: check the maximum number of channels to avoid invalid writes
  - indeo3: fix off by one in MV validity check
  - id3v2: check for end of file while unescaping tags to avoid invalid
@@@ -328,7 -329,7 +328,7 @@@ static inline void mcdc(uint16_t *dst, 
          }
          break;
      default:
-         av_assert2(0);
 -        break;
++        av_assert0(0);
      }
  }
  
@@@ -342,18 -343,16 +342,19 @@@ static int decode_p_block(FourXContext 
                                 BLOCK_TYPE_VLC_BITS, 1);
      uint16_t *start = (uint16_t *)f->last_picture.data[0];
      uint16_t *end   = start + stride * (f->avctx->height - h + 1) - (1 << log2w);
+     int ret;
  
-     av_assert2(code >= 0 && code <= 6);
 -    if (code < 0 || code > 6 || log2w < 0)
 -        return AVERROR_INVALIDDATA;
++    av_assert0(code >= 0 && code <= 6 && log2w >= 0);
  
      if (code == 0) {
 -        src += f->mv[bytestream2_get_byte(&f->g)];
 +        if (bytestream2_get_bytes_left(&f->g) < 1) {
 +            av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n");
-             return;
++            return AVERROR_INVALIDDATA;
 +        }
 +        src += f->mv[bytestream2_get_byteu(&f->g)];
          if (start > src || src > end) {
              av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
-             return;
+             return AVERROR_INVALIDDATA;
          }
          mcdc(dst, src, log2w, h, stride, 1, 0);
      } else if (code == 1) {
      } else if (code == 3 && f->version < 2) {
          mcdc(dst, src, log2w, h, stride, 1, 0);
      } else if (code == 4) {
 -        src += f->mv[bytestream2_get_byte(&f->g)];
 +        if (bytestream2_get_bytes_left(&f->g) < 1) {
 +            av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n");
-             return;
++            return AVERROR_INVALIDDATA;
 +        }
 +        src += f->mv[bytestream2_get_byteu(&f->g)];
          if (start > src || src > end) {
              av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
-             return;
+             return AVERROR_INVALIDDATA;
          }
 -        mcdc(dst, src, log2w, h, stride, 1, bytestream2_get_le16(&f->g2));
 +        if (bytestream2_get_bytes_left(&f->g2) < 2){
 +            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
-             return;
++            return AVERROR_INVALIDDATA;
 +        }
 +        mcdc(dst, src, log2w, h, stride, 1, bytestream2_get_le16u(&f->g2));
      } else if (code == 5) {
 -        mcdc(dst, src, log2w, h, stride, 0, bytestream2_get_le16(&f->g2));
 +        if (bytestream2_get_bytes_left(&f->g2) < 2) {
 +            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
-             return;
++            return AVERROR_INVALIDDATA;
 +        }
 +        mcdc(dst, src, log2w, h, stride, 0, bytestream2_get_le16u(&f->g2));
      } else if (code == 6) {
-             return;
 +        if (bytestream2_get_bytes_left(&f->g2) < 4) {
 +            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
++            return AVERROR_INVALIDDATA;
 +        }
          if (log2w) {
 -            dst[0]      = bytestream2_get_le16(&f->g2);
 -            dst[1]      = bytestream2_get_le16(&f->g2);
 +            dst[0]      = bytestream2_get_le16u(&f->g2);
 +            dst[1]      = bytestream2_get_le16u(&f->g2);
          } else {
 -            dst[0]      = bytestream2_get_le16(&f->g2);
 -            dst[stride] = bytestream2_get_le16(&f->g2);
 +            dst[0]      = bytestream2_get_le16u(&f->g2);
 +            dst[stride] = bytestream2_get_le16u(&f->g2);
          }
      }
+     return 0;
  }
  
  static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)
      const int stride =             f->current_picture.linesize[0] >> 1;
      unsigned int bitstream_size, bytestream_size, wordstream_size, extra,
                   bytestream_offset, wordstream_offset;
 -        memset(f->last_picture.data[0], 0,
 -               f->avctx->height * FFABS(f->last_picture.linesize[0]));
+     int ret;
+     if (!f->last_picture.data[0]) {
+         if ((ret = ff_get_buffer(f->avctx, &f->last_picture)) < 0) {
+             av_log(f->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+             return ret;
+         }
++        for (y=0; y<f->avctx->height; y++)
++            memset(f->last_picture.data[0] + y*f->last_picture.linesize[0], 0, 2*f->avctx->width);
+     }
  
      if (f->version > 1) {
+         if (length < 20)
+             return AVERROR_INVALIDDATA;
          extra           = 20;
 +        if (length < extra)
 +            return -1;
          bitstream_size  = AV_RL32(buf + 8);
          wordstream_size = AV_RL32(buf + 12);
          bytestream_size = AV_RL32(buf + 16);
@@@ -579,7 -576,8 +600,8 @@@ static int decode_i_mb(FourXContext *f
  }
  
  static const uint8_t *read_huffman_tables(FourXContext *f,
-                                           const uint8_t * const buf, int buf_size)
+                                           const uint8_t * const buf,
 -                                          int len)
++                                          int buf_size)
  {
      int frequency[512] = { 0 };
      uint8_t flag[512];
      for (;;) {
          int i;
  
-         if (start <= end && ptr_end - ptr < end - start + 1 + 1)
 -        len -= end - start + 1;
 -
 -        if (end < start || len < 0)
++        if (ptr_end - ptr < FFMAX(end - start + 1, 0) + 1) {
++            av_log(f->avctx, AV_LOG_ERROR, "invalid data in read_huffman_tables\n");
              return NULL;
++        }
          for (i = start; i <= end; i++)
              frequency[i] = *ptr++;
          start = *ptr++;
@@@ -795,30 -797,29 +820,38 @@@ static int decode_frame(AVCodecContext 
      AVFrame *p, temp;
      int i, frame_4cc, frame_size;
  
-     if (buf_size < 12)
+     if (buf_size < 20)
          return AVERROR_INVALIDDATA;
-     frame_4cc = AV_RL32(buf);
-     if (buf_size != AV_RL32(buf + 4) + 8 || buf_size < 20)
++    av_assert0(avctx->width % 16 == 0 && avctx->height % 16 == 0);
++
+     if (buf_size < AV_RL32(buf + 4) + 8) {
          av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n",
                 buf_size, AV_RL32(buf + 4));
+         return AVERROR_INVALIDDATA;
+     }
+     frame_4cc = AV_RL32(buf);
  
      if (frame_4cc == AV_RL32("cfrm")) {
          int free_index       = -1;
+         int id, whole_size;
          const int data_size  = buf_size - 20;
-         const int id         = AV_RL32(buf + 12);
-         const int whole_size = AV_RL32(buf + 16);
          CFrameBuffer *cfrm;
  
-         if (data_size < 0 || whole_size < 0) {
-             av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n");
 -        if (data_size < 0)
++        if (f->version <= 1) {
++            av_log(f->avctx, AV_LOG_ERROR, "cfrm in version %d\n", f->version);
              return AVERROR_INVALIDDATA;
 +        }
  
-         if (f->version <= 1) {
-             av_log(f->avctx, AV_LOG_ERROR, "cfrm in version %d\n", f->version);
+         id         = AV_RL32(buf + 12);
+         whole_size = AV_RL32(buf + 16);
++        if (data_size < 0 || whole_size < 0) {
++            av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
          for (i = 0; i < CFRAME_BUFFER_COUNT; i++)
              if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number)
                  av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n",
      }
  
      if (frame_4cc == AV_RL32("ifr2")) {
 -        p->pict_type = AV_PICTURE_TYPE_I;
 -        if (decode_i2_frame(f, buf - 4, frame_size + 4) < 0)
 +        p->pict_type= AV_PICTURE_TYPE_I;
 +        if (decode_i2_frame(f, buf - 4, frame_size + 4) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode i2 frame failed\n");
              return -1;
 +        }
      } else if (frame_4cc == AV_RL32("ifrm")) {
 -        p->pict_type = AV_PICTURE_TYPE_I;
 -        if (decode_i_frame(f, buf, frame_size) < 0)
 +        p->pict_type= AV_PICTURE_TYPE_I;
 +        if (decode_i_frame(f, buf, frame_size) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode i frame failed\n");
              return -1;
 +        }
      } else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) {
-         if (!f->last_picture.data[0]) {
-             f->last_picture.reference = 3;
-             if (ff_get_buffer(avctx, &f->last_picture) < 0) {
-                 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-                 return -1;
-             }
-             for (i=0; i<avctx->height; i++)
-                 memset(f->last_picture.data[0] + i*f->last_picture.linesize[0], 0, 2*avctx->width);
-         }
--
          p->pict_type = AV_PICTURE_TYPE_P;
 -        if (decode_p_frame(f, buf, frame_size) < 0)
 +        if (decode_p_frame(f, buf, frame_size) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n");
              return -1;
 +        }
      } else if (frame_4cc == AV_RL32("snd_")) {
          av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n",
                 buf_size);
Simple merge
@@@ -91,6 -89,106 +89,108 @@@ static int fourxm_probe(AVProbeData *p
      return AVPROBE_SCORE_MAX;
  }
  
 -
+ static int parse_vtrk(AVFormatContext *s,
+                       FourxmDemuxContext *fourxm, uint8_t *buf, int size,
+                       int left)
+ {
+     AVStream *st;
+     /* check that there is enough data */
+     if (size != vtrk_SIZE || left < size + 8) {
+         return AVERROR_INVALIDDATA;
+     }
+     /* allocate a new AVStream */
+     st = avformat_new_stream(s, NULL);
+     if (!st)
+         return AVERROR(ENOMEM);
+     avpriv_set_pts_info(st, 60, 1, fourxm->fps);
+     fourxm->video_stream_index = st->index;
+     st->codec->codec_type     = AVMEDIA_TYPE_VIDEO;
+     st->codec->codec_id       = AV_CODEC_ID_4XM;
+     st->codec->extradata_size = 4;
+     st->codec->extradata      = av_malloc(4);
+     AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
+     st->codec->width  = AV_RL32(buf + 36);
+     st->codec->height = AV_RL32(buf + 40);
+     return 0;
+ }
+ static int parse_strk(AVFormatContext *s,
+                       FourxmDemuxContext *fourxm, uint8_t *buf, int size,
+                       int left)
+ {
+     AVStream *st;
+     int track;
+     /* check that there is enough data */
+     if (size != strk_SIZE || left < size + 8)
+         return AVERROR_INVALIDDATA;
+     track = AV_RL32(buf + 8);
 -        AudioTrack *tmp = av_realloc(fourxm->tracks,
 -                                     (track + 1) * sizeof(AudioTrack));
 -        if (!tmp)
+     if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
+         av_log(s, AV_LOG_ERROR, "current_track too large\n");
+         return AVERROR_INVALIDDATA;
+     }
+     if (track + 1 > fourxm->track_count) {
 -        fourxm->tracks = tmp;
++        fourxm->tracks = av_realloc_f(fourxm->tracks, track + 1, sizeof(AudioTrack));
++        if (!fourxm->tracks)
+             return AVERROR(ENOMEM);
+         memset(&fourxm->tracks[fourxm->track_count], 0,
+                sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
+         fourxm->track_count = track + 1;
+     }
+     fourxm->tracks[track].adpcm       = AV_RL32(buf + 12);
+     fourxm->tracks[track].channels    = AV_RL32(buf + 36);
+     fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
+     fourxm->tracks[track].bits        = AV_RL32(buf + 44);
+     fourxm->tracks[track].audio_pts   = 0;
+     if (fourxm->tracks[track].channels    <= 0 ||
+         fourxm->tracks[track].sample_rate <= 0 ||
+         fourxm->tracks[track].bits        < 0) {
+         av_log(s, AV_LOG_ERROR, "audio header invalid\n");
+         return AVERROR_INVALIDDATA;
+     }
++    if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) {
++        av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n");
++        return AVERROR_INVALIDDATA;
++    }
++
+     /* allocate a new AVStream */
+     st = avformat_new_stream(s, NULL);
+     if (!st)
+         return AVERROR(ENOMEM);
+     st->id = track;
+     avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
+     fourxm->tracks[track].stream_index = st->index;
+     st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
+     st->codec->codec_tag             = 0;
+     st->codec->channels              = fourxm->tracks[track].channels;
+     st->codec->sample_rate           = fourxm->tracks[track].sample_rate;
+     st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
+     st->codec->bit_rate              = st->codec->channels *
+                                        st->codec->sample_rate *
+                                        st->codec->bits_per_coded_sample;
+     st->codec->block_align           = st->codec->channels *
+                                        st->codec->bits_per_coded_sample;
+     if (fourxm->tracks[track].adpcm){
+         st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
+     } else if (st->codec->bits_per_coded_sample == 8) {
+         st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+     } else
+         st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+     return 0;
+ }
  static int fourxm_read_header(AVFormatContext *s)
  {
      AVIOContext *pb = s->pb;
      /* take the lazy approach and search for any and all vtrk and strk chunks */
      for (i = 0; i < header_size - 8; i++) {
          fourcc_tag = AV_RL32(&header[i]);
-         size = AV_RL32(&header[i + 4]);
+         size       = AV_RL32(&header[i + 4]);
 +        if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) {
 +            av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8);
 +            return AVERROR_INVALIDDATA;
 +        }
  
          if (fourcc_tag == std__TAG) {
-             if (header_size < i + 16) {
+             if (header_size - i < 16) {
 +                av_log(s, AV_LOG_ERROR, "std TAG truncated\n");
-                 return AVERROR_INVALIDDATA;
+                 ret = AVERROR_INVALIDDATA;
+                 goto fail;
              }
              fourxm->fps = av_int2float(AV_RL32(&header[i + 12]));
          } else if (fourcc_tag == vtrk_TAG) {
@@@ -275,15 -282,13 +289,13 @@@ static int fourxm_read_packet(AVFormatC
          if ((ret = avio_read(s->pb, header, 8)) < 0)
              return ret;
          fourcc_tag = AV_RL32(&header[0]);
-         size = AV_RL32(&header[4]);
+         size       = AV_RL32(&header[4]);
 -        if (pb->eof_reached)
 +        if (url_feof(pb))
              return AVERROR(EIO);
          switch (fourcc_tag) {
          case LIST_TAG:
              /* this is a good time to bump the video pts */
-             fourxm->video_pts ++;
+             fourxm->video_pts++;
  
              /* skip the LIST-* tag and move on to the next fourcc */
              avio_rl32(pb);
@@@ -309,8 -308,10 +310,10 @@@ static int smacker_read_packet(AVFormat
                  uint8_t *tmpbuf;
  
                  size = avio_rl32(s->pb) - 4;
-                 if(size + 4L > frame_size)
 -                if (!size || size > frame_size) {
++                if (!size || size + 4L > frame_size) {
+                     av_log(s, AV_LOG_ERROR, "Invalid audio part size\n");
                      return AVERROR_INVALIDDATA;
+                 }
                  frame_size -= size;
                  frame_size -= 4;
                  smk->curstream++;