avcodec/h2645: Fix NAL unit padding
authorMichael Niedermayer <michael@niedermayer.cc>
Thu, 18 Aug 2016 18:41:31 +0000 (20:41 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Thu, 25 Aug 2016 01:29:35 +0000 (03:29 +0200)
The parser changes have lost the support for the needed padding, this adds it back
Fixes out of array reads
Fixes: 03ea21d271abc8acf428d42ace51d8b4/asan_heap-oob_3358eef_5692_16f0cc01ab5225e9ce591659e5c20e35.mkv

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit cc13bc8c4f0f4afa30d0b94c3f3a369ccd2aaf0b)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h2645_parse.c
libavcodec/h2645_parse.h
libavcodec/h264_parse.c
libavcodec/h264_parser.c
libavcodec/hevc.c
libavcodec/hevc_parser.c
libavcodec/qsvenc_hevc.c

index a61379c..a56f900 100644 (file)
@@ -898,7 +898,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
     }
 
     ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc,
-                                h->nal_length_size, avctx->codec_id);
+                                h->nal_length_size, avctx->codec_id, avctx->flags2 & AV_CODEC_FLAG2_FAST);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR,
                "Error splitting the input into NAL units.\n");
index efe3555..309f91d 100644 (file)
@@ -57,8 +57,6 @@
 
 #define MAX_DELAYED_PIC_COUNT  16
 
-#define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes
-
 /* Compiling in interlaced support reduces the speed
  * of progressive decoding by about 2%. */
 #define ALLOW_INTERLACE
index 9979b63..d2fa5a0 100644 (file)
 #include "h2645_parse.h"
 
 int ff_h2645_extract_rbsp(const uint8_t *src, int length,
-                          H2645NAL *nal)
+                          H2645NAL *nal, int small_padding)
 {
     int i, si, di;
     uint8_t *dst;
+    int64_t padding = small_padding ? AV_INPUT_BUFFER_PADDING_SIZE : MAX_MBPAIR_SIZE;
 
     nal->skipped_bytes = 0;
 #define STARTCODE_TEST                                                  \
@@ -81,7 +82,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length,
     }
 #endif /* HAVE_FAST_UNALIGNED */
 
-    if (i >= length - 1) { // no escaped 0
+    if (i >= length - 1 && small_padding) { // no escaped 0
         nal->data     =
         nal->raw_data = src;
         nal->size     =
@@ -90,7 +91,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length,
     }
 
     av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
-                   length + AV_INPUT_BUFFER_PADDING_SIZE);
+                   length + padding);
     if (!nal->rbsp_buffer)
         return AVERROR(ENOMEM);
 
@@ -247,7 +248,7 @@ static int h264_parse_nal_header(H2645NAL *nal, void *logctx)
 
 int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
                           void *logctx, int is_nalff, int nal_length_size,
-                          enum AVCodecID codec_id)
+                          enum AVCodecID codec_id, int small_padding)
 {
     int consumed, ret = 0;
     const uint8_t *next_avc = is_nalff ? buf : buf + length;
@@ -322,7 +323,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
         }
         nal = &pkt->nals[pkt->nb_nals];
 
-        consumed = ff_h2645_extract_rbsp(buf, extract_length, nal);
+        consumed = ff_h2645_extract_rbsp(buf, extract_length, nal, small_padding);
         if (consumed < 0)
             return consumed;
 
index a3c7e1f..6302359 100644 (file)
@@ -26,6 +26,8 @@
 #include "avcodec.h"
 #include "get_bits.h"
 
+#define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes
+
 typedef struct H2645NAL {
     uint8_t *rbsp_buffer;
     int rbsp_buffer_size;
@@ -74,14 +76,14 @@ typedef struct H2645Packet {
  * Extract the raw (unescaped) bitstream.
  */
 int ff_h2645_extract_rbsp(const uint8_t *src, int length,
-                          H2645NAL *nal);
+                          H2645NAL *nal, int small_padding);
 
 /**
  * Split an input packet into NAL units.
  */
 int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
                           void *logctx, int is_nalff, int nal_length_size,
-                          enum AVCodecID codec_id);
+                          enum AVCodecID codec_id, int small_padding);
 
 /**
  * Free all the allocated memory in the packet.
index a63530d..f50f01b 100644 (file)
@@ -327,7 +327,7 @@ static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
     H2645Packet pkt = { 0 };
     int i, ret = 0;
 
-    ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264);
+    ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264, 1);
     if (ret < 0) {
         ret = 0;
         goto fail;
index 52c1d41..2ae9869 100644 (file)
@@ -316,7 +316,7 @@ static inline int parse_nal_units(AVCodecParserContext *s,
             }
             break;
         }
-        consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal);
+        consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal, 1);
         if (consumed < 0)
             break;
 
index b478065..cb1263c 100644 (file)
@@ -2867,7 +2867,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
     /* split the input packet into NAL units, so we know the upper bound on the
      * number of slices in the frame */
     ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff,
-                                s->nal_length_size, s->avctx->codec_id);
+                                s->nal_length_size, s->avctx->codec_id, 1);
     if (ret < 0) {
         av_log(s->avctx, AV_LOG_ERROR,
                "Error splitting the input into NAL units.\n");
index b5633f1..d93586b 100644 (file)
@@ -90,7 +90,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
     int ret, i;
 
     ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0,
-                                AV_CODEC_ID_HEVC);
+                                AV_CODEC_ID_HEVC, 1);
     if (ret < 0)
         return ret;
 
@@ -243,7 +243,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
                 src_length = 20;
         }
 
-        consumed = ff_h2645_extract_rbsp(buf, src_length, nal);
+        consumed = ff_h2645_extract_rbsp(buf, src_length, nal, 1);
         if (consumed < 0)
             return consumed;
 
index 1d1e801..b775ef1 100644 (file)
@@ -69,7 +69,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
     }
 
     /* parse the SPS */
-    ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal);
+    ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal, 1);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
         return ret;