Index: libmpc/trunk/libmpcdec/mpc_demux.c
===================================================================
--- libmpc/trunk/libmpcdec/mpc_demux.c	(revision 466)
+++ libmpc/trunk/libmpcdec/mpc_demux.c	(revision 473)
@@ -72,13 +72,34 @@
 }
 
+// Returns the amount of unread bytes in the demux buffer.
+// Unchecked version - may return a negative value when we've been reading
+// past the end of the valid data as a result of some problem with the file.
+static mpc_int32_t mpc_unread_bytes_unchecked(mpc_demux * d) {
+	return d->bytes_total + d->buffer - d->bits_reader.buff - ((8 - d->bits_reader.count) >> 3);
+}
+
+// Returns the amount of unread bytes in the demux buffer.
+static mpc_uint32_t mpc_unread_bytes(mpc_demux * d) {
+	mpc_int32_t unread_bytes = mpc_unread_bytes_unchecked(d);
+
+	if (unread_bytes < 0) return 0;
+	
+	return (mpc_uint32_t) unread_bytes;
+}
+
+
+
+// Returns the number of bytes available in the buffer.
 static mpc_uint32_t
 mpc_demux_fill(mpc_demux * d, mpc_uint32_t min_bytes, int flags)
 {
-	mpc_uint32_t unread_bytes = d->bytes_total + d->buffer - d->bits_reader.buff
-			- ((8 - d->bits_reader.count) >> 3);
+	mpc_uint32_t unread_bytes = (mpc_uint32_t) mpc_unread_bytes_unchecked(d);
 	int offset = 0;
 
+	if ((mpc_int32_t)
+		unread_bytes < 0) return 0; // Error - we've been reading past the end of the buffer - abort
+
 	if (min_bytes == 0 || min_bytes > DEMUX_BUFFER_SIZE ||
-		    (unread_bytes < min_bytes && flags & MPC_BUFFER_FULL))
+		    (unread_bytes < min_bytes && (flags & MPC_BUFFER_FULL) != 0 ))
 		min_bytes = DEMUX_BUFFER_SIZE;
 
@@ -86,4 +107,5 @@
 		mpc_uint32_t bytes2read = min_bytes - unread_bytes;
 		mpc_uint32_t bytes_free = DEMUX_BUFFER_SIZE - d->bytes_total;
+		mpc_uint32_t bytesread;
 
 		if (flags & MPC_BUFFER_SWAP) {
@@ -102,15 +124,18 @@
 			d->bytes_total = unread_bytes + offset;
 		}
-		bytes2read = d->r->read(d->r, d->buffer + d->bytes_total, bytes2read);
-		if (flags & MPC_BUFFER_SWAP){
+		bytesread = d->r->read(d->r, d->buffer + d->bytes_total, bytes2read);
+		if (bytesread < bytes2read) {
+			memset(d->buffer + d->bytes_total + bytesread, 0, bytes2read - bytesread); // FIXME : why ?
+		}
+		if (flags & MPC_BUFFER_SWAP) {
 			unsigned int i, * tmp = (unsigned int *) (d->buffer + d->bytes_total);
 			for(i = 0 ;i < (bytes2read >> 2); i++)
 				tmp[i] = mpc_swap32(tmp[i]);
 		}
-		d->bytes_total += bytes2read;
-		return bytes2read;
-	}
-
-	return (mpc_uint32_t) -1;
+		d->bytes_total += bytesread;
+		unread_bytes += bytesread;
+	}
+
+	return unread_bytes;
 }
 
@@ -121,5 +146,5 @@
  * @param min_bytes number of bytes to load after seeking
  */
-static void
+static mpc_status
 mpc_demux_seek(mpc_demux * d, mpc_seek_t fpos, mpc_uint32_t min_bytes) {
 	mpc_seek_t start_pos, end_pos;
@@ -141,6 +166,7 @@
 		bit_offset = (int) (fpos - (next_pos << 3));
 
-		d->r->seek(d->r, (mpc_int32_t) next_pos);
 		mpc_demux_clear_buff(d);
+		if (!d->r->seek(d->r, (mpc_int32_t) next_pos))
+			return MPC_STATUS_FAIL;
 	}
 
@@ -151,4 +177,6 @@
 	d->bits_reader.buff += bit_offset >> 3;
 	d->bits_reader.count = 8 - (bit_offset & 7);
+
+	return MPC_STATUS_OK;
 }
 
@@ -170,5 +198,5 @@
  * @param d demuxer context
  * @return size of tag, in bytes
- * @return MPC_STATUS_FILE on errors of any kind
+ * @return MPC_STATUS_FAIL on errors of any kind
  */
 static mpc_int32_t mpc_demux_skip_id3v2(mpc_demux * d)
@@ -193,5 +221,5 @@
 	footerPresent = tmp[0] & 0x10;
 	if ( tmp[0] & 0x0F )
-		return MPC_STATUS_FILE; // not (yet???) allowed
+		return MPC_STATUS_FAIL; // not (yet???) allowed
 
 	tmp[0] = mpc_bits_read(&d->bits_reader, 8); // read size
@@ -201,5 +229,5 @@
 
 	if ( (tmp[0] | tmp[1] | tmp[2] | tmp[3]) & 0x80 )
-		return MPC_STATUS_FILE; // not allowed
+		return MPC_STATUS_FAIL; // not allowed
 
     // read headerSize (syncsave: 4 * $0xxxxxxx = 28 significant bits)
@@ -215,5 +243,6 @@
 	// This is called before file headers get read, streamversion etc isn't yet known, demuxing isn't properly initialized and we can't call mpc_demux_seek() from here.
 	mpc_demux_clear_buff(d);
-	if (!d->r->seek(d->r, size)) return MPC_STATUS_FILE;
+	if (!d->r->seek(d->r, size))
+		return MPC_STATUS_FAIL;
 
 	return size;
@@ -236,5 +265,5 @@
 	d->seek_table = malloc((size_t)(seek_table_size * sizeof(mpc_seek_t)));
 	if (d->seek_table == 0)
-		return MPC_STATUS_FILE;
+		return MPC_STATUS_FAIL;
 	d->seek_table[0] = (mpc_seek_t)mpc_demux_pos(d);
 	d->seek_table_size = 1;
@@ -243,5 +272,5 @@
 }
 
-static void mpc_demux_ST(mpc_demux * d)
+static mpc_status mpc_demux_ST(mpc_demux * d)
 {
 	mpc_uint64_t tmp;
@@ -252,5 +281,5 @@
 
 	if (d->seek_table != 0)
-		return;
+		return MPC_STATUS_OK;
 
 	mpc_bits_get_size(&r, &tmp);
@@ -274,5 +303,5 @@
 
 	if (d->seek_table_size == 1)
-		return;
+		return MPC_STATUS_OK;
 
 	mpc_bits_get_size(&r, &tmp);
@@ -290,7 +319,8 @@
 			table[i >> diff_pwr] = last[i & 1];
 	}
-}
-
-static void mpc_demux_SP(mpc_demux * d, int size, int block_size)
+	return MPC_STATUS_OK;
+}
+
+static mpc_status mpc_demux_SP(mpc_demux * d, int size, int block_size)
 {
 	mpc_seek_t cur;
@@ -301,16 +331,23 @@
 	cur = mpc_demux_pos(d);
 	mpc_bits_get_size(&d->bits_reader, &ptr);
-	mpc_demux_seek(d, (ptr - size) * 8 + cur, 11);
+	MPC_AUTO_FAIL( mpc_demux_seek(d, (ptr - size) * 8 + cur, 11) );
 	st_head_size = mpc_bits_get_block(&d->bits_reader, &b);
 	if (memcmp(b.key, "ST", 2) == 0) {
 		d->chap_pos = (ptr - size + b.size + st_head_size) * 8 + cur;
 		d->chap_nb = -1;
-		mpc_demux_fill(d, (mpc_uint32_t) b.size, 0);
-		mpc_demux_ST(d);
-	}
-	mpc_demux_seek(d, cur, 11 + block_size);
-}
-
-static void mpc_demux_chap_find(mpc_demux * d)
+		if (mpc_demux_fill(d, (mpc_uint32_t) b.size, 0) < b.size)
+			return MPC_STATUS_FAIL;
+		MPC_AUTO_FAIL( mpc_demux_ST(d) );
+	}
+	return mpc_demux_seek(d, cur, 11 + block_size);
+}
+
+static void mpc_demux_chap_empty(mpc_demux * d) {
+	free(d->chap); d->chap = 0;
+	d->chap_nb = 0; // -1 for undefined, 0 for no chapters
+	d->chap_pos = 0;
+}
+
+static mpc_status mpc_demux_chap_find_inner(mpc_demux * d)
 {
 	mpc_block b;
@@ -320,19 +357,24 @@
 
 	if (d->si.stream_version < 8)
-		return;
+		return MPC_STATUS_OK;
 
 	if (d->chap_pos == 0) {
 		mpc_uint64_t cur_pos = (d->si.header_position + 4) * 8;
-		mpc_demux_seek(d, cur_pos, 11); // seek to the beginning of the stream
+		MPC_AUTO_FAIL( mpc_demux_seek(d, cur_pos, 11) ); // seek to the beginning of the stream
 		size = mpc_bits_get_block(&d->bits_reader, &b);
 		while (memcmp(b.key, "SE", 2) != 0) {
-			if (mpc_check_key(b.key) != MPC_STATUS_OK)
-				return;
+			mpc_uint64_t new_pos = cur_pos + (size + b.size) * 8;
+			MPC_AUTO_FAIL(mpc_check_key(b.key));
+
 			if (memcmp(b.key, "CT", 2) == 0) {
 				if (d->chap_pos == 0) d->chap_pos = cur_pos;
-			} else
+			} else {
 				d->chap_pos = 0;
-			cur_pos += (size + b.size) * 8;
-			mpc_demux_seek(d, cur_pos, 11);
+			}
+			if (new_pos <= cur_pos)
+				return MPC_STATUS_FAIL;
+			cur_pos = new_pos;
+			
+			MPC_AUTO_FAIL( mpc_demux_seek(d, cur_pos, 11) );
 			size = mpc_bits_get_block(&d->bits_reader, &b);
 		}
@@ -350,5 +392,5 @@
 		chap_size += size;
 		tag_size += b.size - size;
-		mpc_demux_seek(d, d->chap_pos + (chap_size + tag_size) * 8, 20);
+		MPC_AUTO_FAIL( mpc_demux_seek(d, d->chap_pos + (chap_size + tag_size) * 8, 20) );
 		size = mpc_bits_get_block(&d->bits_reader, &b);
 	}
@@ -357,42 +399,50 @@
 		char * ptag;
 		d->chap = malloc(sizeof(mpc_chap_info) * d->chap_nb + tag_size);
-		if (d->chap != 0) {
-			ptag = (char*)(d->chap + d->chap_nb);
-
-			mpc_demux_seek(d, d->chap_pos, 11);
+		if (d->chap == 0)
+			return MPC_STATUS_FAIL;
+
+		ptag = (char*)(d->chap + d->chap_nb);
+
+		MPC_AUTO_FAIL( mpc_demux_seek(d, d->chap_pos, 11) );
+		size = mpc_bits_get_block(&d->bits_reader, &b);
+		while (memcmp(b.key, "CT", 2) == 0) {
+			mpc_uint_t tmp_size;
+			char * tmp_ptag = ptag;
+			if (mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, 0) < b.size)
+				return MPC_STATUS_FAIL;
+			size = mpc_bits_get_size(&d->bits_reader, &d->chap[i].sample) + 4;
+			d->chap[i].gain = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
+			d->chap[i].peak = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
+
+			tmp_size = b.size - size;
+			do {
+				mpc_uint_t rd_size = tmp_size;
+				mpc_uint8_t * tmp_buff = d->bits_reader.buff + ((8 - d->bits_reader.count) >> 3);
+				mpc_uint32_t avail_bytes = d->bytes_total + d->buffer - tmp_buff;
+				rd_size = mini(rd_size, avail_bytes);
+				memcpy(tmp_ptag, tmp_buff, rd_size);
+				tmp_size -= rd_size;
+				tmp_ptag += rd_size;
+				d->bits_reader.buff += rd_size;
+				mpc_demux_fill(d, tmp_size, 0);
+			} while (tmp_size > 0);
+
+			d->chap[i].tag_size = b.size - size;
+			d->chap[i].tag = ptag;
+			ptag += b.size - size;
+			i++;
 			size = mpc_bits_get_block(&d->bits_reader, &b);
-			while (memcmp(b.key, "CT", 2) == 0) {
-				int tmp_size;
-				char * tmp_ptag = ptag;
-				mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, 0);
-				size = mpc_bits_get_size(&d->bits_reader, &d->chap[i].sample) + 4;
-				d->chap[i].gain = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
-				d->chap[i].peak = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
-
-				tmp_size = b.size - size;
-				do {
-					int rd_size = tmp_size;
-					mpc_uint8_t * tmp_buff = d->bits_reader.buff + ((8 - d->bits_reader.count) >> 3);
-					mpc_uint32_t avail_bytes = d->bytes_total + d->buffer - tmp_buff;
-					rd_size = mini(rd_size, avail_bytes);
-					memcpy(tmp_ptag, tmp_buff, rd_size);
-					tmp_size -= rd_size;
-					tmp_ptag += rd_size;
-					d->bits_reader.buff += rd_size;
-					mpc_demux_fill(d, tmp_size, 0);
-				} while (tmp_size > 0);
-
-				d->chap[i].tag_size = b.size - size;
-				d->chap[i].tag = ptag;
-				ptag += b.size - size;
-				i++;
-				size = mpc_bits_get_block(&d->bits_reader, &b);
-			}
-		} else {
-			d->chap_nb = 0; // malloc failed, chapters will not be available
 		}
 	}
 
 	d->bits_reader.buff -= size;
+	return MPC_STATUS_OK;
+}
+
+static mpc_status mpc_demux_chap_find(mpc_demux * d) {
+	mpc_status s = mpc_demux_chap_find_inner(d);
+	if (MPC_IS_FAILURE(s))
+		mpc_demux_chap_empty(d);
+	return s;
 }
 
@@ -434,5 +484,6 @@
     // get header position
 	d->si.header_position = mpc_demux_skip_id3v2(d);
-	if(d->si.header_position < 0) return MPC_STATUS_FILE;
+	if(d->si.header_position < 0)
+		return MPC_STATUS_FAIL;
 
 	d->si.tag_offset = d->si.total_file_length = d->r->get_size(d->r);
@@ -447,12 +498,9 @@
 		d->si.stream_version = magic[3] & 15;
 		d->si.pns = magic[3] >> 4;
-		if (d->si.stream_version == 7) {
-			mpc_status ret;
-			mpc_demux_fill(d, 6 * 4, MPC_BUFFER_SWAP); // header block size + endian convertion
-			ret = streaminfo_read_header_sv7(&d->si, &d->bits_reader);
-			if (ret != MPC_STATUS_OK) return ret;
-		} else {
-			return MPC_STATUS_INVALIDSV;
-		}
+		if (d->si.stream_version != 7)
+			return MPC_STATUS_FAIL;
+		if (mpc_demux_fill(d, 6 * 4, MPC_BUFFER_SWAP) < 6 * 4) // header block size + endian convertion
+			return MPC_STATUS_FAIL;
+		MPC_AUTO_FAIL( streaminfo_read_header_sv7(&d->si, &d->bits_reader) );
 	} else if (memcmp(magic, "MPCK", 4) == 0) {
 		mpc_block b;
@@ -462,19 +510,22 @@
 		while( memcmp(b.key, "AP", 2) != 0 ){ // scan all blocks until audio
 			if (mpc_check_key(b.key) != MPC_STATUS_OK)
-				return MPC_STATUS_INVALIDSV;
+				return MPC_STATUS_FAIL;
 			if (b.size > (mpc_uint64_t) DEMUX_BUFFER_SIZE - 11)
-				return MPC_STATUS_INVALIDSV;
-			mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, 0);
-			if (memcmp(b.key, "SH", 2) == 0){
-				int ret = streaminfo_read_header_sv8(&d->si, &d->bits_reader, (mpc_uint32_t) b.size);
-				if (ret != MPC_STATUS_OK) return ret;
-			} else if (memcmp(b.key, "RG", 2) == 0)
+				return MPC_STATUS_FAIL;
+			
+			if (mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, 0) <= b.size) 
+				return MPC_STATUS_FAIL;
+
+			if (memcmp(b.key, "SH", 2) == 0) {
+				MPC_AUTO_FAIL( streaminfo_read_header_sv8(&d->si, &d->bits_reader, (mpc_uint32_t) b.size) );
+			} else if (memcmp(b.key, "RG", 2) == 0) {
 				streaminfo_gain(&d->si, &d->bits_reader);
-			else if (memcmp(b.key, "EI", 2) == 0)
+			} else if (memcmp(b.key, "EI", 2) == 0) {
 				streaminfo_encoder_info(&d->si, &d->bits_reader);
-			else if (memcmp(b.key, "SO", 2) == 0)
-				mpc_demux_SP(d, size, (mpc_uint32_t) b.size);
-			else if (memcmp(b.key, "ST", 2) == 0)
-				mpc_demux_ST(d);
+			} else if (memcmp(b.key, "SO", 2) == 0) {
+				MPC_AUTO_FAIL( mpc_demux_SP(d, size, (mpc_uint32_t) b.size) );
+			} else if (memcmp(b.key, "ST", 2) == 0) {
+				MPC_AUTO_FAIL( mpc_demux_ST(d) );
+			}
 			d->bits_reader.buff += b.size;
 			size = mpc_bits_get_block(&d->bits_reader, &b);
@@ -482,7 +533,8 @@
 		d->bits_reader.buff -= size;
 		if (d->si.stream_version == 0) // si not initialized !!!
-			return MPC_STATUS_INVALIDSV;
-	} else
-		return MPC_STATUS_INVALIDSV;
+			return MPC_STATUS_FAIL;
+	} else {
+		return MPC_STATUS_FAIL;
+	}
 
 	return MPC_STATUS_OK;
@@ -525,5 +577,5 @@
 }
 
-mpc_status mpc_demux_decode(mpc_demux * d, mpc_frame_info * i)
+static mpc_status mpc_demux_decode_inner(mpc_demux * d, mpc_frame_info * i)
 {
 	mpc_bits_reader r;
@@ -541,12 +593,14 @@
 			mpc_bits_get_block(&d->bits_reader, &b);
 			while( memcmp(b.key, "AP", 2) != 0 ) { // scan all blocks until audio
-				if (mpc_check_key(b.key) != MPC_STATUS_OK)
-					goto error;
+				MPC_AUTO_FAIL( mpc_check_key(b.key) );
+
 				if (memcmp(b.key, "SE", 2) == 0) { // end block
 					i->bits = -1;
 					return MPC_STATUS_OK;
 				}
-				if (mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, MPC_BUFFER_FULL) == 0)
-					goto error;
+
+				if (mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, MPC_BUFFER_FULL) < b.size) 
+					return MPC_STATUS_FAIL;
+
 				d->bits_reader.buff += b.size;
 				mpc_bits_get_block(&d->bits_reader, &b);
@@ -563,5 +617,5 @@
 		d->block_frames--;
 		if (d->block_bits < 0 || (d->block_frames == 0 && d->block_bits > 7))
-			goto error;
+			return MPC_STATUS_FAIL;
 	} else {
 		if (d->d->decoded_samples == (d->seek_table_size << d->seek_pwr) * MPC_FRAME_LENGTH) {
@@ -575,13 +629,17 @@
 		mpc_decoder_decode_frame(d->d, &d->bits_reader, i);
 		if (i->bits != -1 && d->block_bits != ((d->bits_reader.buff - r.buff) << 3) + r.count - d->bits_reader.count)
-			goto error;
+			return MPC_STATUS_FAIL;
 	}
 	if (i->bits != -1 && d->buffer + d->bytes_total < d->bits_reader.buff + ((8 - d->bits_reader.count) >> 3))
-		goto error;
+		return MPC_STATUS_FAIL;
 
 	return MPC_STATUS_OK;
-error:
+}
+
+mpc_status mpc_demux_decode(mpc_demux * d, mpc_frame_info * i) {
+	mpc_status s = mpc_demux_decode_inner(d, i);
+	if (MPC_IS_FAILURE(s))
 		i->bits = -1; // we pretend it's end of file
-		return MPC_STATUS_INVALIDSV;
+	return s;
 }
 
@@ -658,6 +716,6 @@
 						  mpc_bool_t use_title, mpc_bool_t clip_prevention)
 {
-	float peak = use_title ? d->si.peak_title : d->si.peak_album;
-	float gain = use_title ? d->si.gain_title : d->si.gain_album;
+	float peak = (float) ( use_title ? d->si.peak_title : d->si.peak_album );
+	float gain = (float) ( use_title ? d->si.gain_title : d->si.gain_album );
 
 	if(!use_gain && !clip_prevention)
@@ -667,10 +725,10 @@
 		peak = 1.;
 	else
-		peak = (1 << 15) / pow(10, peak / (20 * 256));
+		peak = (float) ( (1 << 15) / pow(10, peak / (20 * 256)) );
 
 	if(!gain)
 		gain = 1.;
 	else
-		gain = pow(10, (level - gain / 256) / 20);
+		gain = (float) pow(10, (level - gain / 256) / 20);
 
 	if(clip_prevention && (peak < gain || !use_gain))
