vlc | branch: master | Francois Cartegnie <[email protected]> | Mon Apr 27 19:23:49 2020 +0200| [0337ab24f41197f9ab5b7c7e8fe4c4b248e23609] | committer: Francois Cartegnie
packetizer: flac: allow to parse smaller than max header sized blocks > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0337ab24f41197f9ab5b7c7e8fe4c4b248e23609 --- modules/demux/flac.c | 6 ++++-- modules/packetizer/flac.c | 4 ++-- modules/packetizer/flac.h | 29 +++++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/modules/demux/flac.c b/modules/demux/flac.c index 8b1c118047..d63495577c 100644 --- a/modules/demux/flac.c +++ b/modules/demux/flac.c @@ -37,6 +37,7 @@ #include <vlc_charset.h> /* EnsureUTF8 */ #include <assert.h> +#include <limits.h> #include "xiph_metadata.h" /* vorbis comments */ #include "../packetizer/flac.h" @@ -224,10 +225,11 @@ static block_t *GetPacketizedBlock( decoder_t *p_packetizer, block_t *p_block = p_packetizer->pf_packetize( p_packetizer, pp_current_block ); if( p_block ) { - if( p_block->i_buffer >= FLAC_HEADER_SIZE_MAX ) + if( p_block->i_buffer >= FLAC_HEADER_SIZE_MIN && p_block->i_buffer < INT_MAX ) { struct flac_header_info headerinfo = { .i_pts = VLC_TICK_INVALID }; - int i_ret = FLAC_ParseSyncInfo( p_block->p_buffer, streaminfo, NULL, &headerinfo ); + int i_ret = FLAC_ParseSyncInfo( p_block->p_buffer, p_block->i_buffer, + streaminfo, NULL, &headerinfo ); assert( i_ret != 0 ); /* Same as packetizer */ /* Use Frame PTS, not the interpolated one */ p_block->i_dts = p_block->i_pts = headerinfo.i_pts; diff --git a/modules/packetizer/flac.c b/modules/packetizer/flac.c index 0cdfe908f5..d58ee189f2 100644 --- a/modules/packetizer/flac.c +++ b/modules/packetizer/flac.c @@ -366,7 +366,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) return NULL; /* Need more data */ /* Check if frame is valid and get frame info */ - int i_ret = FLAC_ParseSyncInfo(p_header, + int i_ret = FLAC_ParseSyncInfo(p_header, FLAC_HEADER_SIZE_MAX, p_sys->b_stream_info ? &p_sys->stream_info : NULL, flac_crc8, &p_sys->headerinfo); if (!i_ret) { @@ -413,7 +413,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) struct flac_header_info dummy; /* Check if frame is valid and get frame info */ - if(FLAC_ParseSyncInfo(nextheader, + if(FLAC_ParseSyncInfo(nextheader, FLAC_HEADER_SIZE_MAX, p_sys->b_stream_info ? &p_sys->stream_info : NULL, NULL, &dummy) == 0) { diff --git a/modules/packetizer/flac.h b/modules/packetizer/flac.h index 870a30cdf6..2ee0100724 100644 --- a/modules/packetizer/flac.h +++ b/modules/packetizer/flac.h @@ -19,6 +19,7 @@ *****************************************************************************/ #include <vlc_common.h> +#define FLAC_HEADER_SIZE_MIN 9 #define FLAC_HEADER_SIZE_MAX 16 #define FLAC_STREAMINFO_SIZE 34 #define FLAC_FRAME_SIZE_MIN ((48+(8 + 4 + 1*4)+FLAC_HEADER_SIZE_MAX)/8) @@ -64,13 +65,16 @@ static inline void FLAC_ParseStreamInfo( const uint8_t *p_buf, } /* Will return INT64_MAX for an invalid utf-8 sequence */ -static inline int64_t read_utf8(const uint8_t *p_buf, int *pi_read) +static inline int64_t read_utf8(const uint8_t *p_buf, unsigned i_buf, int *pi_read) { /* Max coding bits is 56 - 8 */ /* Value max precision is 36 bits */ int64_t i_result = 0; unsigned i; + if(i_buf < 1) + return INT64_MAX; + if (!(p_buf[0] & 0x80)) { /* 0xxxxxxx */ i_result = p_buf[0]; i = 0; @@ -96,6 +100,9 @@ static inline int64_t read_utf8(const uint8_t *p_buf, int *pi_read) return INT64_MAX; } + if(i_buf < i + 1) + return INT64_MAX; + for (unsigned j = 1; j <= i; j++) { if (!(p_buf[j] & 0x80) || (p_buf[j] & 0x40)) { /* 10xxxxxx */ return INT64_MAX; @@ -114,13 +121,16 @@ static inline int64_t read_utf8(const uint8_t *p_buf, int *pi_read) * - pf_crc8 can be NULL to skip crc check * Returns: 1 on success, 0 on failure, and -1 if could be incorrect *****************************************************************************/ -static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, +static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, unsigned i_buf, const struct flac_stream_info *stream_info, uint8_t(*pf_crc8)(const uint8_t *, size_t), struct flac_header_info *h) { bool b_guessing = false; + if(unlikely(i_buf < FLAC_HEADER_SIZE_MIN)) + return 0; + /* Check syncword */ if (p_buf[0] != 0xFF || (p_buf[1] & 0xFE) != 0xF8) return 0; @@ -205,11 +215,13 @@ static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, return 0; /* End of fixed size header */ - int i_header = 4; + unsigned i_header = 4; + + /* > FLAC_HEADER_SIZE_MIN checks start here */ /* Check Sample/Frame number */ int i_read; - int64_t i_fsnumber = read_utf8(&p_buf[i_header++], &i_read); + int64_t i_fsnumber = read_utf8(&p_buf[i_header++], i_buf - 4, &i_read); if ( i_fsnumber == INT64_MAX ) return 0; @@ -217,6 +229,8 @@ static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, /* Read blocksize */ if (blocksize_hint) { + if(i_header == i_buf) + return 0; blocksize = p_buf[i_header++]; if (blocksize_hint == 7) { blocksize <<= 8; @@ -227,8 +241,12 @@ static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, /* Read sample rate */ if (samplerate == 0) { + if(i_header == i_buf) + return 0; samplerate = p_buf[i_header++]; if (samplerate_hint != 12) { /* 16 bits */ + if(i_header == i_buf) + return 0; samplerate <<= 8; samplerate |= p_buf[i_header++]; } @@ -242,6 +260,9 @@ static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, if ( !samplerate ) return 0; + if(i_header == i_buf) /* no crc space */ + return 0; + /* Check the CRC-8 byte */ if (pf_crc8 && pf_crc8(p_buf, i_header) != p_buf[i_header]) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
