Commit cc13bc8c authored by Michael Niedermayer's avatar Michael Niedermayer

avcodec/h2645: Fix NAL unit padding

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: 's avatarMichael Niedermayer <michael@niedermayer.cc>
parent e2a39b10
...@@ -30,10 +30,11 @@ ...@@ -30,10 +30,11 @@
#include "h2645_parse.h" #include "h2645_parse.h"
int ff_h2645_extract_rbsp(const uint8_t *src, int length, int ff_h2645_extract_rbsp(const uint8_t *src, int length,
H2645NAL *nal) H2645NAL *nal, int small_padding)
{ {
int i, si, di; int i, si, di;
uint8_t *dst; uint8_t *dst;
int64_t padding = small_padding ? AV_INPUT_BUFFER_PADDING_SIZE : MAX_MBPAIR_SIZE;
nal->skipped_bytes = 0; nal->skipped_bytes = 0;
#define STARTCODE_TEST \ #define STARTCODE_TEST \
...@@ -81,7 +82,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, ...@@ -81,7 +82,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length,
} }
#endif /* HAVE_FAST_UNALIGNED */ #endif /* HAVE_FAST_UNALIGNED */
if (i >= length - 1) { // no escaped 0 if (i >= length - 1 && small_padding) { // no escaped 0
nal->data = nal->data =
nal->raw_data = src; nal->raw_data = src;
nal->size = nal->size =
...@@ -90,7 +91,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, ...@@ -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, av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
length + AV_INPUT_BUFFER_PADDING_SIZE); length + padding);
if (!nal->rbsp_buffer) if (!nal->rbsp_buffer)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
...@@ -247,7 +248,7 @@ static int h264_parse_nal_header(H2645NAL *nal, void *logctx) ...@@ -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, int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
void *logctx, int is_nalff, int nal_length_size, void *logctx, int is_nalff, int nal_length_size,
enum AVCodecID codec_id) enum AVCodecID codec_id, int small_padding)
{ {
int consumed, ret = 0; int consumed, ret = 0;
const uint8_t *next_avc = is_nalff ? buf : buf + length; const uint8_t *next_avc = is_nalff ? buf : buf + length;
...@@ -325,7 +326,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, ...@@ -325,7 +326,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
} }
nal = &pkt->nals[pkt->nb_nals]; 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) if (consumed < 0)
return consumed; return consumed;
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "avcodec.h" #include "avcodec.h"
#include "get_bits.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 { typedef struct H2645NAL {
uint8_t *rbsp_buffer; uint8_t *rbsp_buffer;
int rbsp_buffer_size; int rbsp_buffer_size;
...@@ -74,14 +76,14 @@ typedef struct H2645Packet { ...@@ -74,14 +76,14 @@ typedef struct H2645Packet {
* Extract the raw (unescaped) bitstream. * Extract the raw (unescaped) bitstream.
*/ */
int ff_h2645_extract_rbsp(const uint8_t *src, int length, 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. * Split an input packet into NAL units.
*/ */
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
void *logctx, int is_nalff, int nal_length_size, 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. * Free all the allocated memory in the packet.
......
...@@ -337,7 +337,7 @@ static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps, ...@@ -337,7 +337,7 @@ static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
H2645Packet pkt = { 0 }; H2645Packet pkt = { 0 };
int i, ret = 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) { if (ret < 0) {
ret = 0; ret = 0;
goto fail; goto fail;
......
...@@ -318,7 +318,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, ...@@ -318,7 +318,7 @@ static inline int parse_nal_units(AVCodecParserContext *s,
} }
break; 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) if (consumed < 0)
break; break;
......
...@@ -748,7 +748,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) ...@@ -748,7 +748,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, 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) { if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
"Error splitting the input into NAL units.\n"); "Error splitting the input into NAL units.\n");
......
...@@ -55,8 +55,6 @@ ...@@ -55,8 +55,6 @@
#define MAX_DELAYED_PIC_COUNT 16 #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 /* Compiling in interlaced support reduces the speed
* of progressive decoding by about 2%. */ * of progressive decoding by about 2%. */
#define ALLOW_INTERLACE #define ALLOW_INTERLACE
......
...@@ -2867,7 +2867,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) ...@@ -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 /* split the input packet into NAL units, so we know the upper bound on the
* number of slices in the frame */ * number of slices in the frame */
ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff, 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) { if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR, av_log(s->avctx, AV_LOG_ERROR,
"Error splitting the input into NAL units.\n"); "Error splitting the input into NAL units.\n");
......
...@@ -90,7 +90,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, ...@@ -90,7 +90,7 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
int ret, i; int ret, i;
ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0, 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) if (ret < 0)
return ret; return ret;
...@@ -243,7 +243,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, ...@@ -243,7 +243,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
src_length = 20; 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) if (consumed < 0)
return consumed; return consumed;
......
...@@ -69,7 +69,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) ...@@ -69,7 +69,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
} }
/* parse the SPS */ /* 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) { if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n"); av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
return ret; return ret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment