Merge commit 'e930b112d14d7acd050d5087d11b6dd4c56a8e4e' into release/0.10
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 4 Nov 2013 17:04:22 +0000 (18:04 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 4 Nov 2013 17:04:29 +0000 (18:04 +0100)
* commit 'e930b112d14d7acd050d5087d11b6dd4c56a8e4e':
  oma: refactor seek function
  8bps: Bound-check the input buffer
  rtmp: Do not misuse memcmp

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/8bps.c
libavformat/omadec.c
libavformat/rtmppkt.c
libavformat/rtmppkt.h
libavformat/rtmpproto.c

diff --combined libavcodec/8bps.c
@@@ -2,20 -2,20 +2,20 @@@
   * Quicktime Planar RGB (8BPS) Video Decoder
   * Copyright (C) 2003 Roberto Togni
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -27,7 -27,7 +27,7 @@@
   *
   * Supports: PAL8 (RGB 8bpp, paletted)
   *         : BGR24 (RGB 24bpp) (can also output it as RGB32)
 - *         : RGB32 (RGB 32bpp, 4th plane is probably alpha and it's ignored)
 + *         : RGB32 (RGB 32bpp, 4th plane is alpha)
   *
   */
  
@@@ -69,8 -69,9 +69,8 @@@ static int decode_frame(AVCodecContext 
          unsigned char *pixptr, *pixptr_end;
          unsigned int height = avctx->height; // Real image height
          unsigned int dlen, p, row;
-         const unsigned char *lp, *dp;
+         const unsigned char *lp, *dp, *ep;
          unsigned char count;
 -        unsigned int px_inc;
          unsigned int planes = c->planes;
          unsigned char *planemap = c->planemap;
  
                  return -1;
          }
  
+         ep = encoded + buf_size;
          /* Set data pointer after line lengths */
          dp = encoded + planes * (height << 1);
  
 -        /* Ignore alpha plane, don't know what to do with it */
 -        if (planes == 4)
 -                planes--;
 -
 -        px_inc = planes + (avctx->pix_fmt == PIX_FMT_RGB32);
 -
          for (p = 0; p < planes; p++) {
                  /* Lines length pointer for this plane */
                  lp = encoded + p * (height << 1);
                  for(row = 0; row < height; row++) {
                          pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
                          pixptr_end = pixptr + c->pic.linesize[0];
+                         if (ep - lp < row * 2 + 2)
+                             return AVERROR_INVALIDDATA;
                          dlen = av_be2ne16(*(const unsigned short *)(lp+row*2));
                          /* Decode a row of this plane */
                          while(dlen > 0) {
-                                 if(dp + 1 >= buf+buf_size) return -1;
+                                 if(ep - dp <= 1) return -1;
                                  if ((count = *dp++) <= 127) {
                                          count++;
                                          dlen -= count + 1;
 -                                        if (pixptr + count * px_inc > pixptr_end)
 +                                        if (pixptr + count * planes > pixptr_end)
                                              break;
-                                         if(dp + count > buf+buf_size) return -1;
+                                         if(ep - dp < count) return -1;
                                          while(count--) {
                                                  *pixptr = *dp++;
 -                                                pixptr += px_inc;
 +                                                pixptr += planes;
                                          }
                                  } else {
                                          count = 257 - count;
 -                                        if (pixptr + count * px_inc > pixptr_end)
 +                                        if (pixptr + count * planes > pixptr_end)
                                              break;
                                          while(count--) {
                                                  *pixptr = *dp;
 -                                                pixptr += px_inc;
 +                                                pixptr += planes;
                                          }
                                          dp++;
                                          dlen -= 2;
@@@ -155,7 -166,6 +159,7 @@@ static av_cold int decode_init(AVCodecC
  
          c->avctx = avctx;
  
 +        avcodec_get_frame_defaults(&c->pic);
          c->pic.data[0] = NULL;
  
          switch (avctx->bits_per_coded_sample) {
                          c->planemap[0] = 1; // 1st plane is red
                          c->planemap[1] = 2; // 2nd plane is green
                          c->planemap[2] = 3; // 3rd plane is blue
 -                        c->planemap[3] = 0; // 4th plane is alpha???
 +                        c->planemap[3] = 0; // 4th plane is alpha
  #else
                          c->planemap[0] = 2; // 1st plane is red
                          c->planemap[1] = 1; // 2nd plane is green
                          c->planemap[2] = 0; // 3rd plane is blue
 -                        c->planemap[3] = 3; // 4th plane is alpha???
 +                        c->planemap[3] = 3; // 4th plane is alpha
  #endif
                          break;
                  default:
diff --combined libavformat/omadec.c
@@@ -5,20 -5,20 +5,20 @@@
   *               2008 Benjamin Larsson
   *               2011 David Goldwich
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -140,7 -140,7 +140,7 @@@ static int rprobe(AVFormatContext *s, u
      return memcmp(&enc_header[pos], oc->sm_val, 8) ? -1 : 0;
  }
  
 -static int nprobe(AVFormatContext *s, uint8_t *enc_header, const uint8_t *n_val)
 +static int nprobe(AVFormatContext *s, uint8_t *enc_header, int size, const uint8_t *n_val)
  {
      OMAContext *oc = s->priv_data;
      uint32_t pos, taglen, datalen;
      taglen = AV_RB32(&enc_header[pos+32]);
      datalen = AV_RB32(&enc_header[pos+36]) >> 4;
  
 +    if(taglen + (((uint64_t)datalen)<<4) + 44 > size)
 +        return -1;
 +
      pos += 44 + taglen;
  
      av_des_init(&av_des, n_val, 192, 1);
@@@ -232,14 -229,14 +232,14 @@@ static int decrypt_init(AVFormatContex
      }
      if (!memcmp(oc->r_val, (const uint8_t[8]){0}, 8) ||
          rprobe(s, gdata, oc->r_val) < 0 &&
 -        nprobe(s, gdata, oc->n_val) < 0) {
 +        nprobe(s, gdata, geob->datasize, oc->n_val) < 0) {
          int i;
          for (i = 0; i < FF_ARRAY_ELEMS(leaf_table); i += 2) {
              uint8_t buf[16];
              AV_WL64(buf, leaf_table[i]);
              AV_WL64(&buf[8], leaf_table[i+1]);
              kset(s, buf, buf, 16);
 -            if (!rprobe(s, gdata, oc->r_val) || !nprobe(s, gdata, oc->n_val))
 +            if (!rprobe(s, gdata, oc->r_val) || !nprobe(s, gdata, geob->datasize, oc->n_val))
                  break;
          }
          if (i >= sizeof(leaf_table)) {
@@@ -425,22 -422,26 +425,26 @@@ static int oma_read_seek(struct AVForma
  {
      OMAContext *oc = s->priv_data;
  
-     pcm_read_seek(s, stream_index, timestamp, flags);
-     if (oc->encrypted) {
-         /* readjust IV for CBC */
-         int64_t pos = avio_tell(s->pb);
-         if (pos < oc->content_start)
-             memset(oc->iv, 0, 8);
-         else {
-             if (avio_seek(s->pb, -8, SEEK_CUR) < 0 || avio_read(s->pb, oc->iv, 8) < 8) {
-                 memset(oc->iv, 0, 8);
-                 return -1;
-             }
-         }
+     int err = pcm_read_seek(s, stream_index, timestamp, flags);
+     if (!oc->encrypted)
+         return err;
+     /* readjust IV for CBC */
+     if (err || avio_tell(s->pb) < oc->content_start)
+         goto wipe;
+     if ((err = avio_seek(s->pb, -8, SEEK_CUR)) < 0)
+         goto wipe;
+     if ((err = avio_read(s->pb, oc->iv, 8)) < 8) {
+         if (err >= 0)
+             err = AVERROR_EOF;
+         goto wipe;
      }
  
      return 0;
+ wipe:
+     memset(oc->iv, 0, 8);
+     return err;
  }
  
  AVInputFormat ff_oma_demuxer = {
diff --combined libavformat/rtmppkt.c
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP input format
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -279,11 -279,11 +279,11 @@@ int ff_amf_tag_size(const uint8_t *data
                  data++;
                  break;
              }
 -            if (data + size >= data_end || data + size < data)
 +            if (size < 0 || size >= data_end - data)
                  return -1;
              data += size;
              t = ff_amf_tag_size(data, data_end);
 -            if (t < 0 || data + t >= data_end)
 +            if (t < 0 || t >= data_end - data)
                  return -1;
              data += t;
          }
@@@ -312,7 -312,7 +312,7 @@@ int ff_amf_get_field_value(const uint8_
          int size = bytestream_get_be16(&data);
          if (!size)
              break;
 -        if (data + size >= data_end || data + size < data)
 +        if (size < 0 || size >= data_end - data)
              return -1;
          data += size;
          if (size == namelen && !memcmp(data-size, name, namelen)) {
              return 0;
          }
          len = ff_amf_tag_size(data, data_end);
 -        if (len < 0 || data + len >= data_end || data + len < data)
 +        if (len < 0 || len >= data_end - data)
              return -1;
          data += len;
      }
@@@ -363,7 -363,7 +363,7 @@@ static const char* rtmp_packet_type(in
  
  static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end)
  {
 -    int size;
 +    unsigned int size;
      char buf[1024];
  
      if (data >= data_end)
          } else {
              size = bytestream_get_be32(&data);
          }
 -        size = FFMIN(size, 1023);
 +        size = FFMIN(size, sizeof(buf) - 1);
          memcpy(buf, data, size);
          buf[size] = 0;
          av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf);
      case AMF_DATA_TYPE_OBJECT:
          av_log(ctx, AV_LOG_DEBUG, " {\n");
          for (;;) {
 -            int size = bytestream_get_be16(&data);
              int t;
 -            memcpy(buf, data, size);
 -            buf[size] = 0;
 +            size = bytestream_get_be16(&data);
 +            av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1));
              if (!size) {
                  av_log(ctx, AV_LOG_DEBUG, " }\n");
                  data++;
                  break;
              }
 -            if (data + size >= data_end || data + size < data)
 +            if (size >= data_end - data)
                  return;
              data += size;
              av_log(ctx, AV_LOG_DEBUG, "  %s: ", buf);
              ff_amf_tag_contents(ctx, data, data_end);
              t = ff_amf_tag_size(data, data_end);
 -            if (t < 0 || data + t >= data_end)
 +            if (t < 0 || t >= data_end - data)
                  return;
              data += t;
          }
@@@ -447,3 -448,36 +447,36 @@@ void ff_rtmp_packet_dump(void *ctx, RTM
          av_log(ctx, AV_LOG_DEBUG, "\n");
      }
  }
+ int ff_amf_match_string(const uint8_t *data, int size, const char *str)
+ {
+     int len = strlen(str);
+     int amf_len, type;
+     if (size < 1)
+         return 0;
+     type = *data++;
+     if (type != AMF_DATA_TYPE_LONG_STRING &&
+         type != AMF_DATA_TYPE_STRING)
+         return 0;
+     if (type == AMF_DATA_TYPE_LONG_STRING) {
+         if ((size -= 4 + 1) < 0)
+             return 0;
+         amf_len = bytestream_get_be32(&data);
+     } else {
+         if ((size -= 2 + 1) < 0)
+             return 0;
+         amf_len = bytestream_get_be16(&data);
+     }
+     if (amf_len > size)
+         return 0;
+     if (amf_len != len)
+         return 0;
+     return !memcmp(data, str, len);
+ }
diff --combined libavformat/rtmppkt.h
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP packet utilities
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -218,6 -218,13 +218,13 @@@ void ff_amf_write_field_name(uint8_t **
   */
  void ff_amf_write_object_end(uint8_t **dst);
  
+ /**
+  * Match AMF string with a NULL-terminated string.
+  *
+  * @return 0 if the strings do not match.
+  */
+ int ff_amf_match_string(const uint8_t *data, int size, const char *str);
  /** @} */ // AMF funcs
  
  #endif /* AVFORMAT_RTMPPKT_H */
diff --combined libavformat/rtmpproto.c
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP network protocol
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -588,14 -588,14 +588,14 @@@ static int rtmp_parse_result(URLContex
          break;
      case RTMP_PT_INVOKE:
          //TODO: check for the messages sent for wrong state?
-         if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
+         if (ff_amf_match_string(pkt->data, pkt->size, "_error")) {
              uint8_t tmpstr[256];
  
              if (!ff_amf_get_field_value(pkt->data + 9, data_end,
                                          "description", tmpstr, sizeof(tmpstr)))
                  av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
              return -1;
-         } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
+         } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) {
              switch (rt->state) {
              case STATE_HANDSHAKED:
                  if (!rt->is_input) {
                  rt->state = STATE_READY;
                  break;
              }
-         } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
+         } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) {
              const uint8_t* ptr = pkt->data + 11;
              uint8_t tmpstr[256];
  
@@@ -700,7 -700,7 +700,7 @@@ static int get_packet(URLContext *s, in
              }
          }
          rt->bytes_read += ret;
 -        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
 +        if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
              av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
              gen_bytes_read(s, rt, rpkt.timestamp + 1);
              rt->last_bytes_read = rt->bytes_read;
              continue;
          }
          if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
-            (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
+            (rpkt.type == RTMP_PT_NOTIFY &&
+             ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) {
              ts = rpkt.timestamp;
  
              // generate packet header and put data into buffer for FLV demuxer