diff options
-rw-r--r-- | contrib/ffmpeg/A14-aacenc-high-bitrate-crash.patch | 111 |
1 files changed, 94 insertions, 17 deletions
diff --git a/contrib/ffmpeg/A14-aacenc-high-bitrate-crash.patch b/contrib/ffmpeg/A14-aacenc-high-bitrate-crash.patch index 06a640460..1eb260dae 100644 --- a/contrib/ffmpeg/A14-aacenc-high-bitrate-crash.patch +++ b/contrib/ffmpeg/A14-aacenc-high-bitrate-crash.patch @@ -1,28 +1,105 @@ -From 7facbe6793a89ffeda7230d39fce8ccb5ce76208 Mon Sep 17 00:00:00 2001 +From 923c5a378ed4a11817a16a7c1ed3011d7ff72ec8 Mon Sep 17 00:00:00 2001 From: John Stebbins <[email protected]> -Date: Thu, 23 Feb 2017 15:42:02 -0700 -Subject: [PATCH] aacenc: fix crash when encoding at high bitrates +Date: Sun, 26 Feb 2017 09:58:14 -0700 +Subject: [PATCH] put_bits: bounds check buffer -Increases the size of the AVPacket being written into. Although the aac -spec says the max packet size should be 768 * channel count, aacenc -overshoots this and requires a larger buffer. +This prevents invalid writes outside put_bits' buffer. + +It also has the side effect of allowing measurement of the required +size of a buffer without the need to pre-allocate an over-sized buffer. + +This fixes a crash in aacenc.c where it could write past the end of the +allocated packet, which is allocated to be the max size allowed by the +aac spec. aacenc.c uses the above feature to check the size +of encoded data and try again when the size is too large. --- - libavcodec/aacenc.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + libavcodec/aacenc.c | 2 +- + libavcodec/put_bits.h | 25 ++++++++++++++++++++----- + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c -index 9b0e99b..b63affc 100644 +index 9b0e99b..a83b2a8 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c -@@ -572,7 +572,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, +@@ -638,7 +638,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + start_ch += chans; } - start_ch += chans; - } -- if ((ret = ff_alloc_packet(avpkt, 768 * s->channels))) { -+ if ((ret = ff_alloc_packet(avpkt, 8192 * s->channels))) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); - return ret; - } + +- frame_bits = put_bits_count(&s->pb); ++ frame_bits = put_bits_attempted(&s->pb); + if (frame_bits <= 6144 * s->channels - 3) { + s->psy.bitres.bits = frame_bits / s->channels; + break; +diff --git a/libavcodec/put_bits.h b/libavcodec/put_bits.h +index 17666fa..677fecd 100644 +--- a/libavcodec/put_bits.h ++++ b/libavcodec/put_bits.h +@@ -30,6 +30,7 @@ + #include <stddef.h> + #include <assert.h> + ++#include "libavutil/common.h" + #include "libavutil/intreadwrite.h" + + typedef struct PutBitContext { +@@ -62,11 +63,19 @@ static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, + } + + /** ++ * @return the total number of bits attempted to be written to the bitstream. ++ */ ++static inline int put_bits_attempted(PutBitContext *s) ++{ ++ return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; ++} ++ ++/** + * @return the total number of bits written to the bitstream. + */ + static inline int put_bits_count(PutBitContext *s) + { +- return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; ++ return FFMIN(s->size_in_bits, put_bits_attempted(s)); + } + + /** +@@ -89,10 +98,14 @@ static inline void flush_put_bits(PutBitContext *s) + while (s->bit_left < 32) { + /* XXX: should test end of buffer */ + #ifdef BITSTREAM_WRITER_LE +- *s->buf_ptr++ = s->bit_buf; ++ if (s->buf_ptr < s->buf_end) ++ *s->buf_ptr = s->bit_buf; ++ s->buf_ptr++; + s->bit_buf >>= 8; + #else +- *s->buf_ptr++ = s->bit_buf >> 24; ++ if (s->buf_ptr < s->buf_end) ++ *s->buf_ptr = s->bit_buf >> 24; ++ s->buf_ptr++; + s->bit_buf <<= 8; + #endif + s->bit_left += 8; +@@ -145,7 +158,8 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value) + #ifdef BITSTREAM_WRITER_LE + bit_buf |= value << (32 - bit_left); + if (n >= bit_left) { +- AV_WL32(s->buf_ptr, bit_buf); ++ if (s->buf_ptr < s->buf_end) ++ AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + bit_buf = (bit_left == 32) ? 0 : value >> bit_left; + bit_left += 32; +@@ -158,7 +172,8 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value) + } else { + bit_buf <<= bit_left; + bit_buf |= value >> (n - bit_left); +- AV_WB32(s->buf_ptr, bit_buf); ++ if (s->buf_ptr < s->buf_end) ++ AV_WB32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + bit_left += 32 - n; + bit_buf = value; -- 2.9.3 |