Rename _flac_stat to flac_stat_s.
[platform/upstream/flac.git] / src / libFLAC / stream_decoder.c
index 4223ed3..29e4469 100644 (file)
@@ -1,5 +1,5 @@
 /* libFLAC - Free Lossless Audio Codec library
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009  Josh Coalson
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #  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
-#endif
-#endif
+#include "share/compat.h"
 #include "FLAC/assert.h"
+#include "share/alloc.h"
 #include "protected/stream_decoder.h"
 #include "private/bitreader.h"
 #include "private/bitmath.h"
 #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 */
-FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC =
-#if FLAC__HAS_OGG
-       1
+#ifdef FLAC_API_SUPPORTS_OGG_FLAC
+FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = FLAC__HAS_OGG ;
 #else
-       0
+FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = 0 ;
 #endif
-;
 
 
 /***********************************************************************
@@ -181,7 +156,7 @@ typedef struct FLAC__StreamDecoderPrivate {
        FLAC__StreamMetadata seek_table;
        FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */
        FLAC__byte *metadata_filter_ids;
-       unsigned metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */
+       size_t metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */
        FLAC__Frame frame;
        FLAC__bool cached; /* true if there is a byte in lookahead */
        FLAC__CPUInfo cpuinfo;
@@ -280,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);
@@ -307,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_);
@@ -340,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);
@@ -420,8 +397,10 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_(
 #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 = FLAC__lpc_restore_signal_asm_ia32;
                        decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx;
@@ -625,7 +604,7 @@ static FLAC__StreamDecoderInitStatus init_file_internal_(
        if(0 == write_callback || 0 == error_callback)
                return decoder->protected_->state = 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;
@@ -782,7 +761,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*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 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;
                }
@@ -841,7 +820,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*)realloc(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity * 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;
                }
@@ -1285,9 +1264,11 @@ FILE *get_binary_stdin_(void)
         */
 #if defined _MSC_VER || defined __MINGW32__
        _setmode(_fileno(stdin), _O_BINARY);
-#elif defined __CYGWIN__ || defined __EMX__
+#elif defined __CYGWIN__
        /* almost certainly not needed for any modern Cygwin, but let's be safe... */
        setmode(_fileno(stdin), _O_BINARY);
+#elif defined __EMX__
+       setmode(fileno(stdin), O_BINARY);
 #endif
 
        return stdin;
@@ -1321,7 +1302,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*)malloc(sizeof(FLAC__int32)*(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;
@@ -1346,7 +1327,7 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne
 
 FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id)
 {
-       unsigned i;
+       size_t i;
 
        FLAC__ASSERT(0 != decoder);
        FLAC__ASSERT(0 != decoder->private_);
@@ -1402,7 +1383,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 +1448,11 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                        if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8))
                                return false; /* read_callback_ sets the state for us */
 
+                       if(real_length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) { /* underflow check */
+                               decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;/*@@@@@@ maybe wrong error? need to resync?*/
+                               return false;
+                       }
+
                        real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
 
                        if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id))
@@ -1487,7 +1473,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                                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;
                                                }
@@ -1515,7 +1501,7 @@ 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;
                                                }
@@ -1529,7 +1515,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
                        if(!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 */
+                       /* now we have to free any malloc()ed data in the block */
                        switch(type) {
                                case FLAC__METADATA_TYPE_PADDING:
                                        break;
@@ -1669,7 +1655,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*)realloc(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points * 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;
        }
@@ -1708,7 +1694,7 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
        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*)malloc(obj->vendor_string.length+1))) {
+               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;
                }
@@ -1726,7 +1712,7 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
 
        /* read comments */
        if(obj->num_comments > 0) {
-               if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)malloc(obj->num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) {
+               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;
                }
@@ -1735,7 +1721,7 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre
                        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*)malloc(obj->comments[i].length+1))) {
+                               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;
                                }
@@ -1781,7 +1767,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*)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;
                }
@@ -1814,7 +1800,7 @@ 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*)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;
                                }
@@ -1851,7 +1837,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*)malloc(x+1))) {
+       if(0 == (obj->mime_type = safe_malloc_add_2op_(x, /*+*/1))) {
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -1864,7 +1850,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*)malloc(x+1))) {
+       if(0 == (obj->description = safe_malloc_add_2op_(x, /*+*/1))) {
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -1893,7 +1879,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*)malloc(obj->data_length))) {
+       if(0 == (obj->data = safe_malloc_(obj->data_length))) {
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
@@ -1967,7 +1953,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;
@@ -2041,6 +2027,8 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
        }
        if(!read_zero_padding_(decoder))
                return false;
+       if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption (i.e. "zero bits" were not all zeroes) */
+               return true;
 
        /*
         * Read the frame CRC-16 from the footer and check
@@ -2076,7 +2064,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
                                                decoder->private_->output[0][i] = (mid + side) >> 1;
                                                decoder->private_->output[1][i] = (mid - side) >> 1;
 #else
-                                               //@@@@@@ OPT: try without 'side' temp variable
+                                               /* OPT: without 'side' temp variable */
                                                mid = (decoder->private_->output[0][i] << 1) | (decoder->private_->output[1][i] & 1); /* i.e. if 'side' is odd... */
                                                decoder->private_->output[0][i] = (mid + decoder->private_->output[1][i]) >> 1;
                                                decoder->private_->output[1][i] = (mid - decoder->private_->output[1][i]) >> 1;
@@ -2725,7 +2713,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne
                }
        }
 
-       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;
        }
@@ -3007,33 +2995,55 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s
        upper_bound = stream_length;
        upper_bound_sample = total_samples > 0 ? total_samples : target_sample /*estimate it*/;
 
-       /*@@@@@@ add step to validate seek table before using?  encoding to pipe leaves some flac files with incomplete seektables which screw us up */
-       /*@@@@@@ ignore seekpoints where frame_samples = 0 or if point is >= total_samples and total_samples is known (or just alter seek_table in read_metadata_seektable_()) */
-
        /*
         * Now we refine the bounds if we have a seektable with
         * suitable points.  Note that according to the spec they
         * must be ordered by ascending sample number.
+        *
+        * Note: to protect against invalid seek tables we will ignore points
+        * that have frame_samples==0 or sample_number>=total_samples
         */
        if(seek_table) {
+               FLAC__uint64 new_lower_bound = lower_bound;
+               FLAC__uint64 new_upper_bound = upper_bound;
+               FLAC__uint64 new_lower_bound_sample = lower_bound_sample;
+               FLAC__uint64 new_upper_bound_sample = upper_bound_sample;
+
                /* find the closest seek point <= target_sample, if it exists */
                for(i = (int)seek_table->num_points - 1; i >= 0; i--) {
-                       if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && seek_table->points[i].sample_number <= target_sample)
+                       if(
+                               seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
+                               seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */
+                               (total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */
+                               seek_table->points[i].sample_number <= target_sample
+                       )
                                break;
                }
                if(i >= 0) { /* i.e. we found a suitable seek point... */
-                       lower_bound = first_frame_offset + seek_table->points[i].stream_offset;
-                       lower_bound_sample = seek_table->points[i].sample_number;
+                       new_lower_bound = first_frame_offset + seek_table->points[i].stream_offset;
+                       new_lower_bound_sample = seek_table->points[i].sample_number;
                }
 
                /* find the closest seek point > target_sample, if it exists */
                for(i = 0; i < (int)seek_table->num_points; i++) {
-                       if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && seek_table->points[i].sample_number > target_sample)
+                       if(
+                               seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
+                               seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */
+                               (total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */
+                               seek_table->points[i].sample_number > target_sample
+                       )
                                break;
                }
                if(i < (int)seek_table->num_points) { /* i.e. we found a suitable seek point... */
-                       upper_bound = first_frame_offset + seek_table->points[i].stream_offset;
-                       upper_bound_sample = seek_table->points[i].sample_number;
+                       new_upper_bound = first_frame_offset + seek_table->points[i].stream_offset;
+                       new_upper_bound_sample = seek_table->points[i].sample_number;
+               }
+               /* final protection against unsorted seek tables; keep original values if bogus */
+               if(new_upper_bound >= new_lower_bound) {
+                       lower_bound = new_lower_bound;
+                       upper_bound = new_upper_bound;
+                       lower_bound_sample = new_lower_bound_sample;
+                       upper_bound_sample = new_upper_bound_sample;
                }
        }
 
@@ -3115,11 +3125,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;
@@ -3154,12 +3164,12 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint
 {
        FLAC__uint64 left_pos = 0, right_pos = stream_length;
        FLAC__uint64 left_sample = 0, right_sample = FLAC__stream_decoder_get_total_samples(decoder);
-       FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
+       FLAC__uint64 this_frame_sample = (FLAC__uint64)0 - 1;
        FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
        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.
@@ -3203,9 +3213,7 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint
                                /* @@@ TODO: might want to limit pos to some distance
                                 * before EOF, to make sure we land before the last frame,
                                 * thereby getting a this_frame_sample and so having a better
-                                * estimate.  @@@@@@DELETE:this would also mostly (or totally if we could
-                                * be sure to land before the last frame) avoid the
-                                * end-of-stream case we have to check later.
+                                * estimate.
                                 */
                        }
 
@@ -3246,7 +3254,7 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint
                        }
                }
                /* our write callback will change the state when it gets to the target frame */
-               else if(!decoder->private_->is_seeking/*@@@@@@ && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM*/) {
+               else if(!decoder->private_->is_seeking) {
                        break;
                }
                else {
@@ -3311,7 +3319,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;
@@ -3319,7 +3327,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)
@@ -3334,12 +3342,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;