Index: src/libFLAC/stream_decoder.c |
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c |
index 176264867ccdad15e413bf3d87ea693ecefbac17..6632d3127c55783c20c7a3ee3590d5c4c99049b5 100644 |
--- a/src/libFLAC/stream_decoder.c |
+++ b/src/libFLAC/stream_decoder.c |
@@ -1,5 +1,6 @@ |
/* libFLAC - Free Lossless Audio Codec library |
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson |
+ * Copyright (C) 2000-2009 Josh Coalson |
+ * Copyright (C) 2011-2014 Xiph.Org Foundation |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
@@ -29,32 +30,16 @@ |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
-#if HAVE_CONFIG_H |
+#ifdef HAVE_CONFIG_H |
# include <config.h> |
#endif |
-#if defined _MSC_VER || defined __MINGW32__ |
-#include <io.h> /* for _setmode() */ |
-#include <fcntl.h> /* for _O_BINARY */ |
-#endif |
-#if defined __CYGWIN__ || defined __EMX__ |
-#include <io.h> /* for setmode(), O_BINARY */ |
-#include <fcntl.h> /* for _O_BINARY */ |
-#endif |
#include <stdio.h> |
#include <stdlib.h> /* for malloc() */ |
#include <string.h> /* for memset/memcpy() */ |
#include <sys/stat.h> /* for stat() */ |
#include <sys/types.h> /* for off_t */ |
-#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ |
-#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ |
-#define fseeko fseek |
-#define ftello ftell |
-#else |
-#define fseeko _fseeki64 |
-#define ftello _ftelli64 |
-#endif |
-#endif |
+#include "share/compat.h" |
#include "FLAC/assert.h" |
#include "share/alloc.h" |
#include "protected/stream_decoder.h" |
@@ -67,18 +52,7 @@ |
#include "private/lpc.h" |
#include "private/md5.h" |
#include "private/memory.h" |
- |
-#ifdef max |
-#undef max |
-#endif |
-#define max(a,b) ((a)>(b)?(a):(b)) |
- |
-/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ |
-#ifdef _MSC_VER |
-#define FLAC__U64L(x) x |
-#else |
-#define FLAC__U64L(x) x##LLU |
-#endif |
+#include "private/macros.h" |
/* technically this should be in an "export.c" but this is convenient enough */ |
@@ -97,7 +71,7 @@ FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = |
* |
***********************************************************************/ |
-static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; |
+static const FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; |
/*********************************************************************** |
* |
@@ -113,7 +87,7 @@ static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder); |
static FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder); |
static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); |
static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); |
-static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj); |
+static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, unsigned length); |
static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj); |
static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj); |
static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder); |
@@ -168,9 +142,6 @@ typedef struct FLAC__StreamDecoderPrivate { |
void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); |
/* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit): */ |
void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); |
- /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit), AND order <= 8: */ |
- void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); |
- FLAC__bool (*local_bitreader_read_rice_signed_block)(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); |
void *client_data; |
FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */ |
FLAC__BitReader *input; |
@@ -284,18 +255,18 @@ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) |
FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ |
- decoder = (FLAC__StreamDecoder*)calloc(1, sizeof(FLAC__StreamDecoder)); |
+ decoder = calloc(1, sizeof(FLAC__StreamDecoder)); |
if(decoder == 0) { |
return 0; |
} |
- decoder->protected_ = (FLAC__StreamDecoderProtected*)calloc(1, sizeof(FLAC__StreamDecoderProtected)); |
+ decoder->protected_ = calloc(1, sizeof(FLAC__StreamDecoderProtected)); |
if(decoder->protected_ == 0) { |
free(decoder); |
return 0; |
} |
- decoder->private_ = (FLAC__StreamDecoderPrivate*)calloc(1, sizeof(FLAC__StreamDecoderPrivate)); |
+ decoder->private_ = calloc(1, sizeof(FLAC__StreamDecoderPrivate)); |
if(decoder->private_ == 0) { |
free(decoder->protected_); |
free(decoder); |
@@ -311,7 +282,7 @@ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) |
} |
decoder->private_->metadata_filter_ids_capacity = 16; |
- if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { |
+ if(0 == (decoder->private_->metadata_filter_ids = malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { |
FLAC__bitreader_delete(decoder->private_->input); |
free(decoder->private_); |
free(decoder->protected_); |
@@ -344,7 +315,9 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder) |
{ |
unsigned i; |
- FLAC__ASSERT(0 != decoder); |
+ if (decoder == NULL) |
+ return ; |
+ |
FLAC__ASSERT(0 != decoder->protected_); |
FLAC__ASSERT(0 != decoder->private_); |
FLAC__ASSERT(0 != decoder->private_->input); |
@@ -405,7 +378,7 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_( |
#if FLAC__HAS_OGG |
decoder->private_->is_ogg = is_ogg; |
if(is_ogg && !FLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect)) |
- return decoder->protected_->state = FLAC__STREAM_DECODER_OGG_ERROR; |
+ return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; |
#endif |
/* |
@@ -416,42 +389,44 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_( |
decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal; |
decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide; |
decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal; |
- decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal; |
- decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block; |
/* now override with asm where appropriate */ |
#ifndef FLAC__NO_ASM |
if(decoder->private_->cpuinfo.use_asm) { |
#ifdef FLAC__CPU_IA32 |
FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); |
#ifdef FLAC__HAS_NASM |
-#if 1 /*@@@@@@ OPT: not clearly faster, needs more testing */ |
- if(decoder->private_->cpuinfo.data.ia32.bswap) |
- decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap; |
-#endif |
- if(decoder->private_->cpuinfo.data.ia32.mmx) { |
+ decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_asm_ia32; /* OPT_IA32: was really necessary for GCC < 4.9 */ |
+ if(decoder->private_->cpuinfo.ia32.mmx) { |
decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; |
decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx; |
- decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32_mmx; |
} |
else { |
decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; |
decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32; |
- decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32; |
} |
#endif |
-#elif defined FLAC__CPU_PPC |
- FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_PPC); |
- if(decoder->private_->cpuinfo.data.ppc.altivec) { |
- decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ppc_altivec_16; |
- decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8; |
+#ifdef FLAC__HAS_X86INTRIN |
+# if defined FLAC__SSE2_SUPPORTED && !defined FLAC__HAS_NASM /* OPT_SSE: not better than MMX asm */ |
+ if(decoder->private_->cpuinfo.ia32.sse2) { |
+ decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_16_intrin_sse2; |
+ } |
+# endif |
+# if defined FLAC__SSE4_1_SUPPORTED |
+ if(decoder->private_->cpuinfo.ia32.sse41) { |
+ decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_intrin_sse41; |
} |
+# endif |
+#endif |
+#elif defined FLAC__CPU_X86_64 |
+ FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64); |
+ /* No useful SSE optimizations yet */ |
#endif |
} |
#endif |
/* from here on, errors are fatal */ |
- if(!FLAC__bitreader_init(decoder->private_->input, decoder->private_->cpuinfo, read_callback_, decoder)) { |
+ if(!FLAC__bitreader_init(decoder->private_->input, read_callback_, decoder)) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; |
} |
@@ -552,10 +527,10 @@ static FLAC__StreamDecoderInitStatus init_FILE_internal_( |
FLAC__ASSERT(0 != file); |
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) |
- return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; |
+ return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; |
if(0 == write_callback || 0 == error_callback) |
- return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; |
+ return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; |
/* |
* To make sure that our file does not go unclosed after an error, we |
@@ -626,12 +601,12 @@ static FLAC__StreamDecoderInitStatus init_file_internal_( |
* in FLAC__stream_decoder_init_FILE() before the FILE* is assigned. |
*/ |
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) |
- return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; |
+ return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; |
if(0 == write_callback || 0 == error_callback) |
- return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; |
+ return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; |
- file = filename? fopen(filename, "rb") : stdin; |
+ file = filename? flac_fopen(filename, "rb") : stdin; |
if(0 == file) |
return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; |
@@ -675,7 +650,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) |
if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) |
return true; |
- /* see the comment in FLAC__seekable_stream_decoder_reset() as to why we |
+ /* see the comment in FLAC__stream_decoder_reset() as to why we |
* always call FLAC__MD5Final() |
*/ |
FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); |
@@ -788,7 +763,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__ |
FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); |
if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { |
- if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { |
+ if(0 == (decoder->private_->metadata_filter_ids = safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -847,7 +822,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__S |
FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); |
if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { |
- if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { |
+ if(0 == (decoder->private_->metadata_filter_ids = safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1291,7 +1266,7 @@ FILE *get_binary_stdin_(void) |
*/ |
#if defined _MSC_VER || defined __MINGW32__ |
_setmode(_fileno(stdin), _O_BINARY); |
-#elif defined __CYGWIN__ |
+#elif defined __CYGWIN__ |
/* almost certainly not needed for any modern Cygwin, but let's be safe... */ |
setmode(_fileno(stdin), _O_BINARY); |
#elif defined __EMX__ |
@@ -1329,7 +1304,7 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne |
* (at negative indices) for alignment purposes; we use 4 |
* to keep the data well-aligned. |
*/ |
- tmp = (FLAC__int32*)safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/); |
+ tmp = safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/); |
if(tmp == 0) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
@@ -1337,9 +1312,6 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne |
memset(tmp, 0, sizeof(FLAC__int32)*4); |
decoder->private_->output[i] = tmp + 4; |
- /* WATCHOUT: |
- * minimum of quadword alignment for PPC vector optimizations is REQUIRED: |
- */ |
if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
@@ -1389,6 +1361,10 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) |
id = 0; |
continue; |
} |
+ |
+ if(id >= 3) |
+ return false; |
+ |
if(x == ID3V2_TAG_[id]) { |
id++; |
i = 0; |
@@ -1410,7 +1386,7 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) |
decoder->private_->lookahead = (FLAC__byte)x; |
decoder->private_->cached = true; |
} |
- else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ |
+ else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6 sync bits and reserved 7th bit */ |
decoder->private_->header_warmup[1] = (FLAC__byte)x; |
decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; |
return true; |
@@ -1467,6 +1443,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) |
unsigned real_length = length; |
FLAC__StreamMetadata block; |
+ memset(&block, 0, sizeof(block)); |
block.is_last = is_last; |
block.type = (FLAC__MetadataType)type; |
block.length = length; |
@@ -1491,36 +1468,37 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) |
return false; /* read_callback_ sets the state for us */ |
} |
else { |
+ FLAC__bool ok = true; |
switch(type) { |
case FLAC__METADATA_TYPE_PADDING: |
/* skip the padding bytes */ |
if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length)) |
- return false; /* read_callback_ sets the state for us */ |
+ ok = false; /* read_callback_ sets the state for us */ |
break; |
case FLAC__METADATA_TYPE_APPLICATION: |
/* remember, we read the ID already */ |
if(real_length > 0) { |
- if(0 == (block.data.application.data = (FLAC__byte*)malloc(real_length))) { |
+ if(0 == (block.data.application.data = malloc(real_length))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
- return false; |
+ ok = false; |
} |
- if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length)) |
- return false; /* read_callback_ sets the state for us */ |
+ else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length)) |
+ ok = false; /* read_callback_ sets the state for us */ |
} |
else |
block.data.application.data = 0; |
break; |
case FLAC__METADATA_TYPE_VORBIS_COMMENT: |
- if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment)) |
- return false; |
+ if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment, real_length)) |
+ ok = false; |
break; |
case FLAC__METADATA_TYPE_CUESHEET: |
if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet)) |
- return false; |
+ ok = false; |
break; |
case FLAC__METADATA_TYPE_PICTURE: |
if(!read_metadata_picture_(decoder, &block.data.picture)) |
- return false; |
+ ok = false; |
break; |
case FLAC__METADATA_TYPE_STREAMINFO: |
case FLAC__METADATA_TYPE_SEEKTABLE: |
@@ -1528,18 +1506,18 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) |
break; |
default: |
if(real_length > 0) { |
- if(0 == (block.data.unknown.data = (FLAC__byte*)malloc(real_length))) { |
+ if(0 == (block.data.unknown.data = malloc(real_length))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
- return false; |
+ ok = false; |
} |
- if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length)) |
- return false; /* read_callback_ sets the state for us */ |
+ else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length)) |
+ ok = false; /* read_callback_ sets the state for us */ |
} |
else |
block.data.unknown.data = 0; |
break; |
} |
- if(!decoder->private_->is_seeking && decoder->private_->metadata_callback) |
+ if(ok && !decoder->private_->is_seeking && decoder->private_->metadata_callback) |
decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); |
/* now we have to free any malloc()ed data in the block */ |
@@ -1584,6 +1562,9 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) |
free(block.data.unknown.data); |
break; |
} |
+ |
+ if(!ok) /* anything that unsets "ok" should also make sure decoder->protected_->state is updated */ |
+ return false; |
} |
} |
@@ -1682,7 +1663,7 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_ |
decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; |
/* use realloc since we may pass through here several times (e.g. after seeking) */ |
- if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) { |
+ if(0 == (decoder->private_->seek_table.data.seek_table.points = safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1710,58 +1691,88 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_ |
return true; |
} |
-FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj) |
+FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, unsigned length) |
{ |
FLAC__uint32 i; |
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); |
/* read vendor string */ |
- FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); |
- if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) |
- return false; /* read_callback_ sets the state for us */ |
- if(obj->vendor_string.length > 0) { |
- if(0 == (obj->vendor_string.entry = (FLAC__byte*)safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) { |
- decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
- return false; |
- } |
- if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length)) |
+ if (length >= 8) { |
+ length -= 8; /* vendor string length + num comments entries alone take 8 bytes */ |
+ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); |
+ if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) |
return false; /* read_callback_ sets the state for us */ |
- obj->vendor_string.entry[obj->vendor_string.length] = '\0'; |
- } |
- else |
- obj->vendor_string.entry = 0; |
+ if (obj->vendor_string.length > 0) { |
+ if (length < obj->vendor_string.length) { |
+ obj->vendor_string.length = 0; |
+ obj->vendor_string.entry = 0; |
+ goto skip; |
+ } |
+ else |
+ length -= obj->vendor_string.length; |
+ if (0 == (obj->vendor_string.entry = safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) { |
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
+ return false; |
+ } |
+ if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length)) |
+ return false; /* read_callback_ sets the state for us */ |
+ obj->vendor_string.entry[obj->vendor_string.length] = '\0'; |
+ } |
+ else |
+ obj->vendor_string.entry = 0; |
- /* read num comments */ |
- FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); |
- if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) |
- return false; /* read_callback_ sets the state for us */ |
+ /* read num comments */ |
+ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); |
+ if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) |
+ return false; /* read_callback_ sets the state for us */ |
- /* read comments */ |
- if(obj->num_comments > 0) { |
- if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)safe_malloc_mul_2op_(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { |
- decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
- return false; |
- } |
- for(i = 0; i < obj->num_comments; i++) { |
- FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); |
- if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) |
- return false; /* read_callback_ sets the state for us */ |
- if(obj->comments[i].length > 0) { |
- if(0 == (obj->comments[i].entry = (FLAC__byte*)safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) { |
- decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
- return false; |
+ /* read comments */ |
+ if (obj->num_comments > 0) { |
+ if (0 == (obj->comments = safe_malloc_mul_2op_p(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { |
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
+ return false; |
+ } |
+ for (i = 0; i < obj->num_comments; i++) { |
+ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); |
+ if (length < 4) { |
+ obj->num_comments = i; |
+ goto skip; |
} |
- if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) |
+ else |
+ length -= 4; |
+ if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) |
return false; /* read_callback_ sets the state for us */ |
- obj->comments[i].entry[obj->comments[i].length] = '\0'; |
+ if (obj->comments[i].length > 0) { |
+ if (length < obj->comments[i].length) { |
+ obj->comments[i].length = 0; |
+ obj->comments[i].entry = 0; |
+ obj->num_comments = i; |
+ goto skip; |
+ } |
+ else |
+ length -= obj->comments[i].length; |
+ if (0 == (obj->comments[i].entry = safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) { |
+ decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
+ return false; |
+ } |
+ if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) |
+ return false; /* read_callback_ sets the state for us */ |
+ obj->comments[i].entry[obj->comments[i].length] = '\0'; |
+ } |
+ else |
+ obj->comments[i].entry = 0; |
} |
- else |
- obj->comments[i].entry = 0; |
} |
+ else |
+ obj->comments = 0; |
} |
- else { |
- obj->comments = 0; |
+ |
+ skip: |
+ if (length > 0) { |
+ /* This will only happen on files with invalid data in comments */ |
+ if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) |
+ return false; /* read_callback_ sets the state for us */ |
} |
return true; |
@@ -1794,7 +1805,7 @@ FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMet |
obj->num_tracks = x; |
if(obj->num_tracks > 0) { |
- if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { |
+ if(0 == (obj->tracks = safe_calloc_(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1827,18 +1838,18 @@ FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMet |
track->num_indices = (FLAC__byte)x; |
if(track->num_indices > 0) { |
- if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { |
+ if(0 == (track->indices = safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
for(j = 0; j < track->num_indices; j++) { |
- FLAC__StreamMetadata_CueSheet_Index *index = &track->indices[j]; |
- if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN)) |
+ FLAC__StreamMetadata_CueSheet_Index *indx = &track->indices[j]; |
+ if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &indx->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN)) |
return false; /* read_callback_ sets the state for us */ |
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN)) |
return false; /* read_callback_ sets the state for us */ |
- index->number = (FLAC__byte)x; |
+ indx->number = (FLAC__byte)x; |
if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN)) |
return false; /* read_callback_ sets the state for us */ |
@@ -1864,7 +1875,7 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta |
/* read MIME type */ |
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) |
return false; /* read_callback_ sets the state for us */ |
- if(0 == (obj->mime_type = (char*)safe_malloc_add_2op_(x, /*+*/1))) { |
+ if(0 == (obj->mime_type = safe_malloc_add_2op_(x, /*+*/1))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1877,7 +1888,7 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta |
/* read description */ |
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) |
return false; /* read_callback_ sets the state for us */ |
- if(0 == (obj->description = (FLAC__byte*)safe_malloc_add_2op_(x, /*+*/1))) { |
+ if(0 == (obj->description = safe_malloc_add_2op_(x, /*+*/1))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1906,7 +1917,7 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta |
/* read data */ |
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) |
return false; /* read_callback_ sets the state for us */ |
- if(0 == (obj->data = (FLAC__byte*)safe_malloc_(obj->data_length))) { |
+ if(0 == (obj->data = safe_malloc_(obj->data_length))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -1980,7 +1991,7 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) |
decoder->private_->lookahead = (FLAC__byte)x; |
decoder->private_->cached = true; |
} |
- else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ |
+ else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6 sync bits and reserved 7th bit */ |
decoder->private_->header_warmup[1] = (FLAC__byte)x; |
decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; |
return true; |
@@ -2676,12 +2687,8 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un |
if( (FLAC__uint64)order * ((((FLAC__uint64)1)<<bps)-1) * ((1<<subframe->qlp_coeff_precision)-1) < (((FLAC__uint64)-1) << 32) ) |
*/ |
if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) |
- if(bps <= 16 && subframe->qlp_coeff_precision <= 16) { |
- if(order <= 8) |
- decoder->private_->local_lpc_restore_signal_16bit_order8(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); |
- else |
- decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); |
- } |
+ if(bps <= 16 && subframe->qlp_coeff_precision <= 16) |
+ decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); |
else |
decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); |
else |
@@ -2729,18 +2736,20 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne |
if(decoder->private_->frame.header.blocksize < predictor_order) { |
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); |
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; |
- return true; |
+ /* We have received a potentially malicious bit stream. All we can do is error out to avoid a heap overflow. */ |
+ return false; |
} |
} |
else { |
if(partition_samples < predictor_order) { |
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); |
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; |
- return true; |
+ /* We have received a potentially malicious bit stream. All we can do is error out to avoid a heap overflow. */ |
+ return false; |
} |
} |
- if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order))) { |
+ if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, flac_max(6u, partition_order))) { |
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; |
return false; |
} |
@@ -2753,7 +2762,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne |
if(rice_parameter < pesc) { |
partitioned_rice_contents->raw_bits[partition] = 0; |
u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; |
- if(!decoder->private_->local_bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) |
+ if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) |
return false; /* read_callback_ sets the state for us */ |
sample += u; |
} |
@@ -3095,12 +3104,7 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s |
return false; |
} |
#ifndef FLAC__INTEGER_ONLY_LIBRARY |
-#if defined _MSC_VER || defined __MINGW32__ |
- /* with VC++ you have to spoon feed it the casting */ |
- pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(FLAC__int64)(target_sample - lower_bound_sample) / (FLAC__double)(FLAC__int64)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(FLAC__int64)(upper_bound - lower_bound)) - approx_bytes_per_frame; |
-#else |
pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(target_sample - lower_bound_sample) / (FLAC__double)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(upper_bound - lower_bound)) - approx_bytes_per_frame; |
-#endif |
#else |
/* a little less accurate: */ |
if(upper_bound - lower_bound < 0xffffffff) |
@@ -3152,11 +3156,11 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s |
} |
/* our last move backwards wasn't big enough, try again */ |
approx_bytes_per_frame = approx_bytes_per_frame? approx_bytes_per_frame * 2 : 16; |
- continue; |
+ continue; |
} |
/* allow one seek over upper bound, so we can get a correct upper_bound_sample for streams with unknown total_samples */ |
first_seek = false; |
- |
+ |
/* make sure we are not seeking in corrupted stream */ |
if (this_frame_sample < lower_bound_sample) { |
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; |
@@ -3196,7 +3200,7 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint |
FLAC__bool did_a_seek; |
unsigned iteration = 0; |
- /* In the first iterations, we will calculate the target byte position |
+ /* In the first iterations, we will calculate the target byte position |
* by the distance from the target sample to left_sample and |
* right_sample (let's call it "proportional search"). After that, we |
* will switch to binary search. |
@@ -3224,12 +3228,7 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint |
} |
else { |
#ifndef FLAC__INTEGER_ONLY_LIBRARY |
-#if defined _MSC_VER || defined __MINGW32__ |
- /* with MSVC you have to spoon feed it the casting */ |
- pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); |
-#else |
pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); |
-#endif |
#else |
/* a little less accurate: */ |
if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) |
@@ -3346,7 +3345,7 @@ FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *dec |
if(decoder->private_->file == stdin) |
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; |
- else if(fseeko(decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) |
+ else if(fseeko(decoder->private_->file, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0) |
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; |
else |
return FLAC__STREAM_DECODER_SEEK_STATUS_OK; |
@@ -3354,7 +3353,7 @@ FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *dec |
FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) |
{ |
- off_t pos; |
+ FLAC__off_t pos; |
(void)client_data; |
if(decoder->private_->file == stdin) |
@@ -3369,12 +3368,12 @@ FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *dec |
FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) |
{ |
- struct stat filestats; |
+ struct flac_stat_s filestats; |
(void)client_data; |
if(decoder->private_->file == stdin) |
return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; |
- else if(fstat(fileno(decoder->private_->file), &filestats) != 0) |
+ else if(flac_fstat(fileno(decoder->private_->file), &filestats) != 0) |
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; |
else { |
*stream_length = (FLAC__uint64)filestats.st_size; |