| 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;
|
|
|