I've uploaded xine-lib 1.1.14-4 to testing-proposed-updates. This is required due to a versioned dependency on libjack0 which would be generated were it uploaded to unstable (to which I've uploaded 1.1.16.1-1). Most of the changes since 1.1.14-3 are security-related, and one fixes a possible FTBFS. A complete diff is attached; if you want to view the changes individually, see http://hg.debian.org/hg/xine-lib/pkg/xine-lib-deb-lenny. (The packaging VCS URL in debian/control is wrong, but for this upload that doesn't matter since the information is all there in the "wrong" place.) -- | Darren Salt | linux or ds at | nr. Ashington, | Toon | RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army | + Output less CO2 => avoid boiling weather. TIME IS RUNNING OUT *FAST*. Fatal error in Reality (invalid parameter '-utopia')
diff --git a/debian/changelog b/debian/changelog
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,27 @@ xine-lib (1.1.14-3) unstable; urgency=hi
+xine-lib (1.1.14-4) testing-proposed-updates; urgency=high
+
+ * Security fixes backported from 1.1.16:
+ - CVE-2008-5234: Heap overflow in Quicktime atom parsing.
+ (Closes: #508313)
+ - CVE-2008-5236: Multiple buffer overflows. (Closes: #509521)
+ - CVE-2008-5237: Multiple integer overflows. (Closes: #509265)
+ - CVE-2008-5239: Unchecked or incompletely-checked read function results.
+ (Closes: #509353)
+ - CVE-2008-5240 & CVE-2008-5242: Unchecked memory allocations using
+ untrusted values. (Closes: #509352, #507165)
+ - CVE-2008-5241: Integer underflow in qt compressed atom handling.
+ (Closes: #509008)
+ - CVE-2008-5243: Buffer indexing using untrusted or unchecked values.
+ - Avoid segfault on invalid track type in Matroska files.
+ - Avoid underflow (compressed atoms) in the Qt demuxer.
+ * Other backports from 1.1.16:
+ - Fix a couple of potential hangs, both of which can be triggered by an
+ MMS stream in which the demuxer cannot find a valid GUID.
+ - Avoid possible hangs with xxmc, reported to happen with openchrome.
+ * Fix FTBFS on i386 (with amd64 kernel). (Closes: #510662)
+
+ -- Darren Salt <linux@youmustbejoking.demon.co.uk> Wed, 07 Jan 2009 18:57:29 +0000
+
xine-lib (1.1.14-3) unstable; urgency=high
* More security fixes from upstream hg:
diff --git a/debian/rules b/debian/rules
--- a/debian/rules
+++ b/debian/rules
@@ -44,6 +44,8 @@ endif
# set configure flags here
CONFIGURE_FLAGS := \
+ --build $(DEB_BUILD_GNU_TYPE) \
+ --host $(DEB_HOST_GNU_TYPE) \
--prefix=/usr \
--mandir=\$${prefix}/share/man \
--with-external-libmad \
diff --git a/misc/cdda_server.c b/misc/cdda_server.c
--- a/misc/cdda_server.c
+++ b/misc/cdda_server.c
@@ -480,6 +480,12 @@ static int process_commands( int socket
sscanf(cmd,"%*s %d %d", &start_frame, &num_frames);
+ if (num_frames > INT_MAX / CD_RAW_FRAME_SIZE)
+ {
+ printf ("fatal error: integer overflow\n");
+ exit (1);
+ }
+
n = num_frames * CD_RAW_FRAME_SIZE;
buf = malloc( n );
if( !buf )
@@ -556,6 +562,11 @@ static int process_commands( int socket
char *buf;
sscanf(cmd,"%*s %d %d", &blocks, &flags);
+ if (blocks > INT_MAX / DVD_BLOCK_SIZE)
+ {
+ printf ("fatal error: integer overflow\n");
+ exit (1);
+ }
n = blocks * DVD_BLOCK_SIZE;
buf = malloc( n );
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -247,6 +247,8 @@ static void ff_audio_decode_data (audio_
if (extradata + data_len > this->size)
break; /* abort early - extradata length is bad */
+ if (extradata > INT_MAX - data_len)
+ break;/*integer overflow*/
this->context->extradata_size = data_len;
this->context->extradata = malloc(this->context->extradata_size +
@@ -365,6 +367,11 @@ static void ff_audio_decode_data (audio_
/* dispatch the decoded audio */
out = 0;
while (out < decode_buffer_size) {
+ int stream_status = xine_get_status(this->stream);
+
+ if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP)
+ return;
+
audio_buffer =
this->stream->audio_out->get_buffer (this->stream->audio_out);
if (audio_buffer->mem_size == 0) {
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -605,6 +605,10 @@ static void ff_convert_frame(ff_video_de
su = this->av_frame->data[1];
sv = this->av_frame->data[2];
+ /* Some segfaults & heap corruption have been observed with img->height,
+ * so we use this->bih.biHeight instead (which is the displayed height)
+ */
+
if (this->context->pix_fmt == PIX_FMT_YUV410P) {
yuv9_to_yv12(
@@ -625,7 +629,7 @@ static void ff_convert_frame(ff_video_de
img->pitches[2],
/* width x height */
img->width,
- img->height);
+ this->bih.biHeight);
} else if (this->context->pix_fmt == PIX_FMT_YUV411P) {
@@ -647,7 +651,7 @@ static void ff_convert_frame(ff_video_de
img->pitches[2],
/* width x height */
img->width,
- img->height);
+ this->bih.biHeight);
} else if (this->context->pix_fmt == PIX_FMT_RGBA32) {
@@ -655,7 +659,7 @@ static void ff_convert_frame(ff_video_de
uint32_t *argb_pixels;
uint32_t argb;
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
argb_pixels = (uint32_t *)sy;
for(x = 0; x < img->width; x++) {
uint8_t r, g, b;
@@ -683,7 +687,7 @@ static void ff_convert_frame(ff_video_de
uint8_t *src;
uint16_t pixel16;
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
src = sy;
for(x = 0; x < img->width; x++) {
uint8_t r, g, b;
@@ -712,7 +716,7 @@ static void ff_convert_frame(ff_video_de
uint8_t *src;
uint16_t pixel16;
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
src = sy;
for(x = 0; x < img->width; x++) {
uint8_t r, g, b;
@@ -740,7 +744,7 @@ static void ff_convert_frame(ff_video_de
int x, plane_ptr = 0;
uint8_t *src;
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
src = sy;
for(x = 0; x < img->width; x++) {
uint8_t r, g, b;
@@ -764,7 +768,7 @@ static void ff_convert_frame(ff_video_de
int x, plane_ptr = 0;
uint8_t *src;
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
src = sy;
for(x = 0; x < img->width; x++) {
uint8_t r, g, b;
@@ -807,7 +811,7 @@ static void ff_convert_frame(ff_video_de
v_palette[x] = COMPUTE_V(r, g, b);
}
- for(y = 0; y < img->height; y++) {
+ for(y = 0; y < this->bih.biHeight; y++) {
src = sy;
for(x = 0; x < img->width; x++) {
pixel = *src++;
@@ -824,7 +828,7 @@ static void ff_convert_frame(ff_video_de
} else {
- for (y=0; y<img->height; y++) {
+ for (y = 0; y < this->bih.biHeight; y++) {
xine_fast_memcpy (dy, sy, img->width);
dy += img->pitches[0];
@@ -832,7 +836,7 @@ static void ff_convert_frame(ff_video_de
sy += this->av_frame->linesize[0];
}
- for (y=0; y<(img->height/2); y++) {
+ for (y = 0; y < this->bih.biHeight / 2; y++) {
if (this->context->pix_fmt != PIX_FMT_YUV444P) {
diff --git a/src/demuxers/demux_aac.c b/src/demuxers/demux_aac.c
--- a/src/demuxers/demux_aac.c
+++ b/src/demuxers/demux_aac.c
@@ -176,7 +176,7 @@ static int demux_aac_send_chunk(demux_pl
buf->extra_info->input_time = (8*current_pos) / (bitrate/1000);
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c
--- a/src/demuxers/demux_ac3.c
+++ b/src/demuxers/demux_ac3.c
@@ -308,13 +308,7 @@ static int demux_ac3_send_chunk (demux_p
this->frame_size);
}
- if (buf->size == 0) {
- buf->free_buffer(buf);
- this->status = DEMUX_FINISHED;
- return this->status;
- }
-
- if (buf->size == 0) {
+ if (buf->size <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.c
@@ -738,7 +738,10 @@ static void asf_send_buffer_nodefrag (de
bufsize = stream->fifo->buffer_pool_buf_size;
buf = stream->fifo->buffer_pool_alloc (stream->fifo);
- this->input->read (this->input, buf->content, bufsize);
+ if (this->input->read (this->input, buf->content, bufsize) != bufsize) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n");
+ return ;
+ }
lprintf ("data: %d %d %d %d\n", buf->content[0], buf->content[1], buf->content[2], buf->content[3]);
@@ -817,7 +820,10 @@ static void asf_send_buffer_defrag (demu
if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: buffer overflow on defrag!\n");
} else {
- this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len);
+ if (this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len) != frag_len) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n");
+ return ;
+ }
stream->frag_offset += frag_len;
}
diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c
--- a/src/demuxers/demux_dts.c
+++ b/src/demuxers/demux_dts.c
@@ -269,7 +269,7 @@ static int demux_dts_send_chunk (demux_p
this->frame_size);
}
- if (buf->size == 0) {
+ if (buf->size <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c
--- a/src/demuxers/demux_matroska.c
+++ b/src/demuxers/demux_matroska.c
@@ -607,6 +607,8 @@ static void init_codec_xiph(demux_matros
int i;
uint8_t *data;
+ if (track->codec_private_len < 3)
+ return;
nb_lace = track->codec_private[0];
if (nb_lace != 2)
return;
@@ -614,6 +616,8 @@ static void init_codec_xiph(demux_matros
frame[0] = track->codec_private[1];
frame[1] = track->codec_private[2];
frame[2] = track->codec_private_len - frame[0] - frame[1] - 3;
+ if (frame[2] < 0)
+ return;
data = track->codec_private + 3;
for (i = 0; i < 3; i++) {
@@ -1179,7 +1183,12 @@ static int parse_track_entry(demux_matro
break;
case MATROSKA_ID_TR_CODECPRIVATE: {
- char *codec_private = malloc (elem.len);
+ char *codec_private;
+ if (elem.len >= 0x80000000)
+ return 0;
+ codec_private = malloc (elem.len);
+ if (! codec_private)
+ return 0;
lprintf("CodecPrivate\n");
if (!ebml_read_binary(ebml, &elem, codec_private)) {
free(codec_private);
@@ -1283,12 +1292,14 @@ static int parse_track_entry(demux_matro
if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_VFW_FOURCC)) {
xine_bmiheader *bih;
- lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n");
- bih = (xine_bmiheader*)track->codec_private;
- _x_bmiheader_le2me(bih);
+ if (track->codec_private_len >= sizeof(xine_bmiheader)) {
+ lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n");
+ bih = (xine_bmiheader*)track->codec_private;
+ _x_bmiheader_le2me(bih);
- track->buf_type = _x_fourcc_to_buf_video(bih->biCompression);
- init_codec = init_codec_video;
+ track->buf_type = _x_fourcc_to_buf_video(bih->biCompression);
+ init_codec = init_codec_video;
+ }
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_UNCOMPRESSED)) {
} else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_SP)) ||
@@ -1297,6 +1308,9 @@ static int parse_track_entry(demux_matro
xine_bmiheader *bih;
lprintf("MATROSKA_CODEC_ID_V_MPEG4_*\n");
+ if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader))
+ track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader);
+
/* create a bitmap info header struct for MPEG 4 */
bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len);
bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len;
@@ -1318,6 +1332,9 @@ static int parse_track_entry(demux_matro
xine_bmiheader *bih;
lprintf("MATROSKA_CODEC_ID_V_MPEG4_AVC\n");
+ if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader))
+ track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader);
+
/* create a bitmap info header struct for h264 */
bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len);
bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len;
@@ -1394,11 +1411,13 @@ static int parse_track_entry(demux_matro
xine_waveformatex *wfh;
lprintf("MATROSKA_CODEC_ID_A_ACM\n");
- wfh = (xine_waveformatex*)track->codec_private;
- _x_waveformatex_le2me(wfh);
+ if (track->codec_private_len >= sizeof(xine_waveformatex)) {
+ wfh = (xine_waveformatex*)track->codec_private;
+ _x_waveformatex_le2me(wfh);
- track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag);
- init_codec = init_codec_audio;
+ track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag);
+ init_codec = init_codec_audio;
+ }
} else if (!strncmp(track->codec_id, MATROSKA_CODEC_ID_A_AAC,
sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) {
lprintf("MATROSKA_CODEC_ID_A_AAC\n");
@@ -1479,9 +1498,14 @@ static int parse_track_entry(demux_matro
break;
}
- if (init_codec)
+ if (init_codec) {
+ if (! track->fifo) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: Error: fifo not set up for track of type type %" PRIu32 "\n", track->track_type);
+ return 0;
+ }
init_codec(this, track);
-
+ }
}
}
@@ -1807,6 +1831,11 @@ static int read_block_data (demux_matros
alloc_block_data(this, len);
/* block datas */
+ if (! this->block_data) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: memory allocation error\n");
+ return 0;
+ }
if (this->input->read(this->input, this->block_data, len) != len) {
off_t pos = this->input->get_current_pos(this->input);
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c
--- a/src/demuxers/demux_mng.c
+++ b/src/demuxers/demux_mng.c
@@ -104,13 +104,21 @@ static mng_bool mymng_read_stream(mng_ha
static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread){
demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
- *bytesread = this->input->read(this->input, buffer, size);
+ off_t n = this->input->read(this->input, buffer, size);
+ if (n < 0) {
+ *bytesread = 0;
+ return MNG_FALSE;
+ }
+ *bytesread = n;
return MNG_TRUE;
}
static mng_bool mymng_process_header(mng_handle mngh, mng_uint32 width, mng_uint32 height){
demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+
+ if (width > 0x8000 || height > 0x8000)
+ return MNG_FALSE;
this->bih.biWidth = (width + 7) & ~7;
this->bih.biHeight = height;
diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c
--- a/src/demuxers/demux_mod.c
+++ b/src/demuxers/demux_mod.c
@@ -130,9 +130,16 @@ static int probe_mod_file(demux_mod_t *t
/* returns 1 if the MOD file was opened successfully, 0 otherwise */
static int open_mod_file(demux_mod_t *this) {
int total_read;
+ off_t input_length;
/* Get size and create buffer */
- this->filesize = this->input->get_length(this->input);
+ input_length = this->input->get_length(this->input);
+ /* Avoid potential issues with signed variables and e.g. read() returning -1 */
+ if (input_length > 0x7FFFFFFF || input_length < 0) {
+ xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - size overflow\n");
+ return 0;
+ }
+ this->filesize = input_length;
this->buffer = (char *)malloc(this->filesize);
if(!this->buffer) {
xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - allocation failure\n");
diff --git a/src/demuxers/demux_mpc.c b/src/demuxers/demux_mpc.c
--- a/src/demuxers/demux_mpc.c
+++ b/src/demuxers/demux_mpc.c
@@ -214,7 +214,7 @@ static int demux_mpc_send_chunk(demux_pl
/* Read data */
bytes_read = this->input->read(this->input, buf->content, bytes_to_read);
- if(bytes_read == 0) {
+ if(bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
--- a/src/demuxers/demux_mpeg.c
+++ b/src/demuxers/demux_mpeg.c
@@ -279,6 +279,10 @@ static void parse_mpeg2_packet (demux_mp
if((this->dummy_space[0] & 0xE0) == 0x20) {
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
track = (this->dummy_space[0] & 0x1f);
@@ -298,6 +302,10 @@ static void parse_mpeg2_packet (demux_mp
int spu_id = this->dummy_space[1] & 0x03;
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_SPU_SVCD + spu_id;
buf->pts = pts;
@@ -318,6 +326,10 @@ static void parse_mpeg2_packet (demux_mp
if((this->dummy_space[0] & 0xfc) == 0x00) {
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_SPU_CVD + (this->dummy_space[0] & 0x03);
buf->pts = pts;
@@ -376,6 +388,10 @@ static void parse_mpeg2_packet (demux_mp
i = this->input->read (this->input, this->dummy_space+1, 6);
buf = this->input->read_block (this->input, this->video_fifo, len-7);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_AUDIO_LPCM_BE + track;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
@@ -920,7 +936,7 @@ static void demux_mpeg_resync (demux_mpe
if (pos == len) {
len = this->input->read(this->input, dummy_buf, sizeof(dummy_buf));
pos = 0;
- if (len == 0) {
+ if (len <= 0) {
this->status = DEMUX_FINISHED;
break;
}
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
--- a/src/demuxers/demux_mpeg_block.c
+++ b/src/demuxers/demux_mpeg_block.c
@@ -1190,14 +1190,14 @@ static int demux_mpeg_detect_blocksize(d
input_plugin_t *input)
{
input->seek(input, 2048, SEEK_SET);
- if (!input->read(input, this->scratch, 4))
+ if (input->read(input, this->scratch, 4) != 4)
return 0;
if (this->scratch[0] || this->scratch[1]
|| (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) {
input->seek(input, 2324, SEEK_SET);
- if (!input->read(input, this->scratch, 4))
+ if (input->read(input, this->scratch, 4) != 4)
return 0;
if (this->scratch[0] || this->scratch[1]
|| (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba))
@@ -1417,7 +1417,7 @@ static demux_plugin_t *open_plugin (demu
}
input->seek(input, 0, SEEK_SET);
- if (input->read(input, this->scratch, this->blocksize)) {
+ if (input->read(input, this->scratch, this->blocksize) == this->blocksize) {
lprintf("open_plugin:read worked\n");
if (this->scratch[0] || this->scratch[1]
diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c
--- a/src/demuxers/demux_mpeg_pes.c
+++ b/src/demuxers/demux_mpeg_pes.c
@@ -1687,7 +1687,7 @@ static demux_plugin_t *open_plugin (demu
if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) {
input->seek(input, 0, SEEK_SET);
- if (input->read(input, (char *)this->scratch, 6)) {
+ if (input->read(input, (char *)this->scratch, 6) == 6) {
lprintf("open_plugin:read worked\n");
if (this->scratch[0] || this->scratch[1]
diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c
--- a/src/demuxers/demux_nsf.c
+++ b/src/demuxers/demux_nsf.c
@@ -128,7 +128,7 @@ static int demux_nsf_send_chunk(demux_pl
buf->type = BUF_AUDIO_NSF;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
/* the file has been completely loaded, free the buffer and start
* sending control buffers */
buf->free_buffer(buf);
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
--- a/src/demuxers/demux_ogg.c
+++ b/src/demuxers/demux_ogg.c
@@ -237,7 +237,7 @@ static int read_ogg_packet (demux_ogg_t
while (ogg_sync_pageout(&this->oy,&this->og)!=1) {
buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE);
bytes = this->input->read(this->input, buffer, CHUNKSIZE);
- if (bytes == 0) {
+ if (bytes <= 0) {
if (total == 0) {
lprintf("read_ogg_packet read nothing\n");
return 0;
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -738,6 +738,8 @@ static void parse_meta_atom(qt_info *inf
if (current_atom == ART_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->artist = xine_xmalloc(string_size);
if (info->artist) {
strncpy(info->artist, &meta_atom[i + 20], string_size - 1);
@@ -745,6 +747,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == NAM_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->name = xine_xmalloc(string_size);
if (info->name) {
strncpy(info->name, &meta_atom[i + 20], string_size - 1);
@@ -752,6 +756,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == ALB_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->album = xine_xmalloc(string_size);
if (info->album) {
strncpy(info->album, &meta_atom[i + 20], string_size - 1);
@@ -759,6 +765,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == GEN_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->genre = xine_xmalloc(string_size);
if (info->genre) {
strncpy(info->genre, &meta_atom[i + 20], string_size - 1);
@@ -766,6 +774,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == TOO_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->comment = xine_xmalloc(string_size);
if (info->comment) {
strncpy(info->comment, &meta_atom[i + 20], string_size - 1);
@@ -773,6 +783,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == WRT_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->composer = xine_xmalloc(string_size);
if (info->composer) {
strncpy(info->composer, &meta_atom[i + 20], string_size - 1);
@@ -780,6 +792,8 @@ static void parse_meta_atom(qt_info *inf
}
} else if (current_atom == DAY_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->year = xine_xmalloc(string_size);
if (info->year) {
strncpy(info->year, &meta_atom[i + 20], string_size - 1);
@@ -947,6 +961,10 @@ static qt_error parse_trak_atom (qt_trak
/* allocate space for each of the properties unions */
trak->stsd_atoms_count = _X_BE_32(&trak_atom[i + 8]);
+ if (trak->stsd_atoms_count <= 0) {
+ last_error = QT_HEADER_TROUBLE;
+ goto free_trak;
+ }
trak->stsd_atoms = calloc(trak->stsd_atoms_count, sizeof(properties_t));
if (!trak->stsd_atoms) {
last_error = QT_NO_MEMORY;
@@ -958,6 +976,10 @@ static qt_error parse_trak_atom (qt_trak
for (k = 0; k < trak->stsd_atoms_count; k++) {
current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]);
+ if (current_stsd_atom_size < 4) {
+ last_error = QT_HEADER_TROUBLE;
+ goto free_trak;
+ }
if (trak->type == MEDIA_VIDEO) {
@@ -1575,13 +1597,16 @@ static qt_error parse_reference_atom (re
qt_atom current_atom;
unsigned int current_atom_size;
+ if (ref_atom_size >= 0x80000000)
+ return QT_NOT_A_VALID_FILE;
+
/* initialize reference atom */
ref->url = NULL;
ref->data_rate = 0;
ref->qtim_version = 0;
/* traverse through the atom looking for the key atoms */
- for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) {
+ for (i = ATOM_PREAMBLE_SIZE; i + 4 < ref_atom_size; i++) {
current_atom_size = _X_BE_32(&ref_atom[i - 4]);
current_atom = _X_BE_32(&ref_atom[i]);
@@ -1590,7 +1615,7 @@ static qt_error parse_reference_atom (re
size_t string_size = _X_BE_32(&ref_atom[i + 12]);
size_t url_offset = 0;
- if (string_size >= current_atom_size || i + string_size >= ref_atom_size)
+ if (string_size >= current_atom_size || string_size >= ref_atom_size - i)
return QT_NOT_A_VALID_FILE;
/* if the URL starts with "http://", copy it */
@@ -1598,6 +1623,8 @@ static qt_error parse_reference_atom (re
memcmp(&ref_atom[i + 16], "rtsp://", 7) &&
base_mrl )
url_offset = strlen(base_mrl);
+ if (url_offset >= 0x80000000)
+ return QT_NOT_A_VALID_FILE;
/* otherwise, append relative URL to base MRL */
string_size += url_offset;
@@ -2181,7 +2208,7 @@ static qt_error open_qt_file(qt_info *in
}
/* check if moov is compressed */
- if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM) {
+ if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM && moov_atom_size >= 0x28) {
info->compressed_header = 1;
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -58,12 +58,10 @@
#include "real_common.h"
#define FOURCC_TAG BE_FOURCC
-#define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F')
#define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P')
#define MDPR_TAG FOURCC_TAG('M', 'D', 'P', 'R')
#define CONT_TAG FOURCC_TAG('C', 'O', 'N', 'T')
#define DATA_TAG FOURCC_TAG('D', 'A', 'T', 'A')
-#define INDX_TAG FOURCC_TAG('I', 'N', 'D', 'X')
#define RA_TAG FOURCC_TAG('.', 'r', 'a', 0xfd)
#define VIDO_TAG FOURCC_TAG('V', 'I', 'D', 'O')
@@ -176,6 +174,18 @@ typedef struct {
demux_class_t demux_class;
} demux_real_class_t;
+static int is_indx_tag(const void *ptr) {
+ return memcmp(ptr, "INDX", 4) == 0;
+}
+
+static int is_data_tag(const void *ptr) {
+ return memcmp(ptr, "DATA", 4) == 0;
+}
+
+static int is_rmf_tag(const void *ptr) {
+ return memcmp(ptr, ".RMF", 4) == 0;
+}
+
static void real_parse_index(demux_real_t *this) {
off_t next_index_chunk = this->index_start;
@@ -183,8 +193,6 @@ static void real_parse_index(demux_real_
unsigned char index_chunk_header[INDEX_CHUNK_HEADER_SIZE];
unsigned char index_record[INDEX_RECORD_SIZE];
int i;
- unsigned int entries, stream_num;
- real_index_entry_t **index;
while(next_index_chunk) {
lprintf("reading index chunk at %"PRIX64"\n", next_index_chunk);
@@ -200,70 +208,68 @@ static void real_parse_index(demux_real_
}
/* Check chunk is actually an index chunk */
- if(_X_BE_32(&index_chunk_header[0]) == INDX_TAG) {
- unsigned short version;
+ if(!is_indx_tag(&index_chunk_header[0])) {
+ lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]);
+ break;
+ }
- /* Check version */
- version = _X_BE_16(&index_chunk_header[8]);
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in INDX: 0x%04x\n", version);
- break;
+ /* Check version */
+ const uint16_t version = _X_BE_16(&index_chunk_header[8]);
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in INDX: 0x%04x\n", version);
+ break;
+ }
+
+ /* Read data from header */
+ const uint32_t entries = _X_BE_32(&index_chunk_header[10]);
+ const uint16_t stream_num = _X_BE_16(&index_chunk_header[14]);
+ next_index_chunk = _X_BE_32(&index_chunk_header[16]);
+
+ /* Find which stream this index is for */
+ real_index_entry_t **index = NULL;
+ for(i = 0; i < this->num_video_streams; i++) {
+ if(stream_num == this->video_streams[i].mdpr->stream_number) {
+ index = &this->video_streams[i].index;
+ this->video_streams[i].index_entries = entries;
+ lprintf("found index chunk for video stream with num %d\n", stream_num);
+ break;
}
+ }
- /* Read data from header */
- entries = _X_BE_32(&index_chunk_header[10]);
- stream_num = _X_BE_16(&index_chunk_header[14]);
- next_index_chunk = _X_BE_32(&index_chunk_header[16]);
+ if(!index) {
+ for(i = 0; i < this->num_audio_streams; i++) {
+ if(stream_num == this->audio_streams[i].mdpr->stream_number) {
+ index = &this->audio_streams[i].index;
+ this->audio_streams[i].index_entries = entries;
+ lprintf("found index chunk for audio stream with num %d\n", stream_num);
+ break;
+ }
+ }
+ }
- /* Find which stream this index is for */
- index = NULL;
- for(i = 0; i < this->num_video_streams; i++) {
- if(stream_num == this->video_streams[i].mdpr->stream_number) {
- index = &this->video_streams[i].index;
- this->video_streams[i].index_entries = entries;
- lprintf("found index chunk for video stream with num %d\n", stream_num);
- break;
- }
- }
+ if(index && entries)
+ /* Allocate memory for index */
+ *index = calloc(entries, sizeof(real_index_entry_t));
+
+ if(index && entries && *index) {
+ /* Read index */
+ for(i = 0; i < entries; i++) {
+ if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE)
+ != INDEX_RECORD_SIZE) {
+ lprintf("index record not read\n");
+ free(*index);
+ *index = NULL;
+ break;
+ }
- if(!index) {
- for(i = 0; i < this->num_audio_streams; i++) {
- if(stream_num == this->audio_streams[i].mdpr->stream_number) {
- index = &this->audio_streams[i].index;
- this->audio_streams[i].index_entries = entries;
- lprintf("found index chunk for audio stream with num %d\n", stream_num);
- break;
- }
- }
- }
-
- if(index && entries)
- /* Allocate memory for index */
- *index = calloc(entries, sizeof(real_index_entry_t));
-
- if(index && entries && *index) {
- /* Read index */
- for(i = 0; i < entries; i++) {
- if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE)
- != INDEX_RECORD_SIZE) {
- lprintf("index record not read\n");
- free(*index);
- *index = NULL;
- break;
- }
-
- (*index)[i].timestamp = _X_BE_32(&index_record[2]);
- (*index)[i].offset = _X_BE_32(&index_record[6]);
- (*index)[i].packetno = _X_BE_32(&index_record[10]);
- }
- } else {
- lprintf("unused index chunk with %d entries for stream num %d\n",
- entries, stream_num);
+ (*index)[i].timestamp = _X_BE_32(&index_record[2]);
+ (*index)[i].offset = _X_BE_32(&index_record[6]);
+ (*index)[i].packetno = _X_BE_32(&index_record[10]);
}
} else {
- lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]);
- break;
+ lprintf("unused index chunk with %d entries for stream num %d\n",
+ entries, stream_num);
}
}
@@ -324,18 +330,19 @@ static void real_free_mdpr (mdpr_t *mdpr
}
static void real_parse_audio_specific_data (demux_real_t *this,
- real_stream_t * stream,
- uint8_t * data, int len)
+ real_stream_t * stream)
{
- int coded_frame_size;
- int codec_data_length;
- int coded_frame_size2;
- int subpacket_size;
+ if (stream->mdpr->type_specific_len < 46) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_real: audio data size smaller than header length!\n");
+ return;
+ }
- coded_frame_size = _X_BE_32 (data+24);
- codec_data_length = _X_BE_16 (data+40);
- coded_frame_size2 = _X_BE_16 (data+42);
- subpacket_size = _X_BE_16 (data+44);
+ uint8_t * data = stream->mdpr->type_specific_data;
+ const uint32_t coded_frame_size = _X_BE_32 (data+24);
+ const uint16_t codec_data_length = _X_BE_16 (data+40);
+ const uint16_t coded_frame_size2 = _X_BE_16 (data+42);
+ const uint16_t subpacket_size = _X_BE_16 (data+44);
stream->sps = subpacket_size;
stream->w = coded_frame_size2;
@@ -365,15 +372,20 @@ static void real_parse_audio_specific_da
"demux_real: error, i don't handle buf type 0x%08x\n", stream->buf_type);
}
- if (stream->sps) {
- stream->frame_size = stream->w / stream->sps * stream->h * stream->sps;
- stream->frame_buffer = xine_xmalloc (stream->frame_size);
- stream->frame_num_bytes = 0;
+ /*
+ * when stream->sps is set it used to do this:
+ * stream->frame_size = stream->w / stream->sps * stream->h * stream->sps;
+ * but it looks pointless? the compiler will probably optimise it away, I suppose?
+ */
+ if (stream->w < 32768 && stream->h < 32768) {
+ stream->frame_size = stream->w * stream->h;
+ stream->frame_buffer = calloc(stream->frame_size, 1);
} else {
- stream->frame_size = stream->w * stream->h;
- stream->frame_buffer = xine_xmalloc (stream->frame_size);
- stream->frame_num_bytes = 0;
+ stream->frame_size = 0;
+ stream->frame_buffer = NULL;
}
+
+ stream->frame_num_bytes = 0;
stream->sub_packet_cnt = 0;
if (!stream->frame_buffer)
@@ -391,37 +403,35 @@ static void real_parse_headers (demux_re
char preamble[PREAMBLE_SIZE];
unsigned int chunk_type = 0;
unsigned int chunk_size;
- unsigned short version;
- unsigned char *chunk_buffer;
- int field_size;
- int stream_ptr;
- unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
- unsigned char signature[REAL_SIGNATURE_SIZE];
+
+ if (INPUT_IS_SEEKABLE(this->input))
+ this->input->seek (this->input, 0, SEEK_SET);
+
+ {
+ uint8_t signature[REAL_SIGNATURE_SIZE];
+ if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) !=
+ REAL_SIGNATURE_SIZE) {
+
+ lprintf ("signature not read\n");
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+
+ if ( !is_rmf_tag(signature) ) {
+ this->status = DEMUX_FINISHED;
+ lprintf ("signature not found '%.4s'\n", signature);
+ return;
+ }
+
+ /* skip to the start of the first chunk and start traversing */
+ chunk_size = _X_BE_32(&signature[4]);
+ }
this->data_start = 0;
this->data_size = 0;
this->num_video_streams = 0;
this->num_audio_streams = 0;
- if (INPUT_IS_SEEKABLE(this->input))
- this->input->seek (this->input, 0, SEEK_SET);
-
- if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) !=
- REAL_SIGNATURE_SIZE) {
-
- lprintf ("signature not read\n");
- this->status = DEMUX_FINISHED;
- return;
- }
-
- if (_X_BE_32(signature) != RMF_TAG) {
- this->status = DEMUX_FINISHED;
- lprintf ("signature not found '%.4s'\n", signature);
- return;
- }
-
- /* skip to the start of the first chunk and start traversing */
- chunk_size = _X_BE_32(&signature[4]);
this->input->seek(this->input, chunk_size-8, SEEK_CUR);
/* iterate through chunks and gather information until the first DATA
@@ -442,183 +452,185 @@ static void real_parse_headers (demux_re
case PROP_TAG:
case MDPR_TAG:
case CONT_TAG:
+ {
+ if (chunk_size < PREAMBLE_SIZE+1) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+ chunk_size -= PREAMBLE_SIZE;
+ uint8_t *const chunk_buffer = malloc(chunk_size);
+ if (! chunk_buffer ||
+ this->input->read(this->input, chunk_buffer, chunk_size) !=
+ chunk_size) {
+ free (chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+
+ uint16_t version = _X_BE_16(&chunk_buffer[0]);
- chunk_size -= PREAMBLE_SIZE;
- chunk_buffer = malloc(chunk_size);
- if (this->input->read(this->input, chunk_buffer, chunk_size) !=
- chunk_size) {
- free (chunk_buffer);
- this->status = DEMUX_FINISHED;
- return;
- }
+ if (chunk_type == PROP_TAG) {
- version = _X_BE_16(&chunk_buffer[0]);
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demuxe_real: unknown object version in PROP: 0x%04x\n", version);
+ free(chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
- if (chunk_type == PROP_TAG) {
-
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demuxe_real: unknown object version in PROP: 0x%04x\n", version);
- free(chunk_buffer);
- this->status = DEMUX_FINISHED;
- return;
- }
+ this->duration = _X_BE_32(&chunk_buffer[22]);
+ this->index_start = _X_BE_32(&chunk_buffer[30]);
+ this->data_start = _X_BE_32(&chunk_buffer[34]);
+ this->avg_bitrate = _X_BE_32(&chunk_buffer[6]);
- this->duration = _X_BE_32(&chunk_buffer[22]);
- this->index_start = _X_BE_32(&chunk_buffer[30]);
- this->data_start = _X_BE_32(&chunk_buffer[34]);
- this->avg_bitrate = _X_BE_32(&chunk_buffer[6]);
+ lprintf("PROP: duration: %d ms\n", this->duration);
+ lprintf("PROP: index start: %"PRIX64"\n", this->index_start);
+ lprintf("PROP: data start: %"PRIX64"\n", this->data_start);
+ lprintf("PROP: average bit rate: %"PRId64"\n", this->avg_bitrate);
- lprintf("PROP: duration: %d ms\n", this->duration);
- lprintf("PROP: index start: %"PRIX64"\n", this->index_start);
- lprintf("PROP: data start: %"PRIX64"\n", this->data_start);
- lprintf("PROP: average bit rate: %"PRId64"\n", this->avg_bitrate);
+ if (this->avg_bitrate<1)
+ this->avg_bitrate = 1;
- if (this->avg_bitrate<1)
- this->avg_bitrate = 1;
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE,
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE,
this->avg_bitrate);
- } else if (chunk_type == MDPR_TAG) {
+ } else if (chunk_type == MDPR_TAG) {
+ if (version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in MDPR: 0x%04x\n", version);
+ free(chunk_buffer);
+ continue;
+ }
+
+ mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer);
- mdpr_t *mdpr;
- uint32_t fourcc;
+ lprintf ("parsing type specific data...\n");
+ if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) {
+ lprintf ("mpeg layer 3 audio detected...\n");
- if (version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in MDPR: 0x%04x\n", version);
- free(chunk_buffer);
- continue;
- }
-
- mdpr = real_parse_mdpr (chunk_buffer);
+ static const uint32_t fourcc = ME_FOURCC('a', 'd', 'u', 0x55);
+ this->audio_streams[this->num_audio_streams].fourcc = fourcc;
+ this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
+ this->audio_streams[this->num_audio_streams].index = NULL;
+ this->audio_streams[this->num_audio_streams].mdpr = mdpr;
+ this->num_audio_streams++;
+ } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG &&
+ mdpr->type_specific_len >= 6) {
+ if(this->num_audio_streams == MAX_AUDIO_STREAMS) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: maximum number of audio stream exceeded\n");
+ goto unknown;
+ }
+
+ const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4);
- lprintf ("parsing type specific data...\n");
- if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) {
- lprintf ("mpeg layer 3 audio detected...\n");
+ lprintf("audio version %d detected\n", version);
- fourcc = ME_FOURCC('a', 'd', 'u', 0x55);
- this->audio_streams[this->num_audio_streams].fourcc = fourcc;
- this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
- this->audio_streams[this->num_audio_streams].index = NULL;
- this->audio_streams[this->num_audio_streams].mdpr = mdpr;
- this->num_audio_streams++;
- } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) {
- int version, len;
-
- if(this->num_audio_streams == MAX_AUDIO_STREAMS) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: maximum number of audio stream exceeded\n");
- goto unknown;
- }
-
- version = _X_BE_16(mdpr->type_specific_data + 4);
-
- lprintf("audio version %d detected\n", version);
-
- switch(version) {
+ char *fourcc_ptr = "\0\0\0";
+ switch(version) {
case 3:
/* Version 3 header stores fourcc after meta info - cheat by reading backwards from the
* end of the header instead of having to parse it all */
- fourcc = _X_ME_32(mdpr->type_specific_data + mdpr->type_specific_len - 5);
+ if (mdpr->type_specific_len >= 5)
+ fourcc_ptr = mdpr->type_specific_data + mdpr->type_specific_len - 5;
break;
- case 4:
- len = *(mdpr->type_specific_data + 56);
- fourcc = _X_ME_32(mdpr->type_specific_data + 58 + len);
+ case 4: {
+ if (mdpr->type_specific_len >= 57) {
+ const uint8_t len = *(mdpr->type_specific_data + 56);
+ if (mdpr->type_specific_len >= 62 + len)
+ fourcc_ptr = mdpr->type_specific_data + 58 + len;
+ }
+ }
break;
case 5:
- fourcc = _X_ME_32(mdpr->type_specific_data + 66);
+ if (mdpr->type_specific_len >= 70)
+ fourcc_ptr = mdpr->type_specific_data + 66;
break;
default:
lprintf("unsupported audio header version %d\n", version);
goto unknown;
- }
+ }
+ lprintf("fourcc = %.4s\n", fourcc_ptr);
- lprintf("fourcc = %.4s\n", (char *) &fourcc);
+ const uint32_t fourcc = _X_ME_32(fourcc_ptr);
- this->audio_streams[this->num_audio_streams].fourcc = fourcc;
- this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
- this->audio_streams[this->num_audio_streams].index = NULL;
- this->audio_streams[this->num_audio_streams].mdpr = mdpr;
+ this->audio_streams[this->num_audio_streams].fourcc = fourcc;
+ this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
+ this->audio_streams[this->num_audio_streams].index = NULL;
+ this->audio_streams[this->num_audio_streams].mdpr = mdpr;
- real_parse_audio_specific_data (this,
- &this->audio_streams[this->num_audio_streams],
- mdpr->type_specific_data,
- mdpr->type_specific_len);
- this->num_audio_streams++;
+ real_parse_audio_specific_data (this,
+ &this->audio_streams[this->num_audio_streams]);
+ this->num_audio_streams++;
- } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG) {
+ } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG &&
+ mdpr->type_specific_len >= 34) {
- if(this->num_video_streams == MAX_VIDEO_STREAMS) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: maximum number of video stream exceeded\n");
- goto unknown;
- }
+ if(this->num_video_streams == MAX_VIDEO_STREAMS) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: maximum number of video stream exceeded\n");
+ goto unknown;
+ }
- lprintf ("video detected\n");
- fourcc = _X_ME_32(mdpr->type_specific_data + 8);
- lprintf("fourcc = %.4s\n", (char *) &fourcc);
+ lprintf ("video detected\n");
+ const uint32_t fourcc = _X_ME_32(mdpr->type_specific_data + 8);
+ lprintf("fourcc = %.4s\n", (char *) &fourcc);
- this->video_streams[this->num_video_streams].fourcc = fourcc;
- this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc);
- this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30);
- this->video_streams[this->num_video_streams].index = NULL;
- this->video_streams[this->num_video_streams].mdpr = mdpr;
+ this->video_streams[this->num_video_streams].fourcc = fourcc;
+ this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc);
+ this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30);
+ this->video_streams[this->num_video_streams].index = NULL;
+ this->video_streams[this->num_video_streams].mdpr = mdpr;
- this->num_video_streams++;
+ this->num_video_streams++;
- } else {
- lprintf("unrecognised type specific data\n");
+ } else {
+ lprintf("unrecognised type specific data\n");
-unknown:
- real_free_mdpr(mdpr);
- }
+ unknown:
+ real_free_mdpr(mdpr);
+ }
- } else if (chunk_type == CONT_TAG) {
+ } else if (chunk_type == CONT_TAG) {
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in CONT: 0x%04x\n", version);
- free(chunk_buffer);
- continue;
- }
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in CONT: 0x%04x\n", version);
+ free(chunk_buffer);
+ continue;
+ }
- stream_ptr = 2;
+ int stream_ptr = 2;
+#define SET_METADATA_STRING(type) \
+ do { \
+ const uint16_t field_size = _X_BE_16(&chunk_buffer[stream_ptr]); \
+ stream_ptr += 2; \
+ _x_meta_info_n_set(this->stream, type, \
+ &chunk_buffer[stream_ptr], field_size); \
+ stream_ptr += field_size; \
+ } while(0)
- /* load the title string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
+ /* load the title string */
+ SET_METADATA_STRING(XINE_META_INFO_TITLE);
+
+ /* load the author string */
+ SET_METADATA_STRING(XINE_META_INFO_ARTIST);
- /* load the author string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
+ /* load the copyright string as the year */
+ SET_METADATA_STRING(XINE_META_INFO_YEAR);
- /* load the copyright string as the year */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
+ /* load the comment string */
+ SET_METADATA_STRING(XINE_META_INFO_COMMENT);
+ }
- /* load the comment string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_COMMENT,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
+ free(chunk_buffer);
}
-
- free(chunk_buffer);
break;
- case DATA_TAG:
+ case DATA_TAG: {
+ uint8_t data_chunk_header[DATA_CHUNK_HEADER_SIZE];
+
if (this->input->read(this->input, data_chunk_header,
DATA_CHUNK_HEADER_SIZE) != DATA_CHUNK_HEADER_SIZE) {
this->status = DEMUX_FINISHED;
@@ -626,7 +638,7 @@ unknown:
}
/* check version */
- version = _X_BE_16(&data_chunk_header[0]);
+ const uint16_t version = _X_BE_16(&data_chunk_header[0]);
if(version != 0) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: unknown object version in DATA: 0x%04x\n", version);
@@ -637,7 +649,8 @@ unknown:
this->current_data_chunk_packet_count = _X_BE_32(&data_chunk_header[2]);
this->next_data_chunk_offset = _X_BE_32(&data_chunk_header[6]);
this->data_chunk_size = chunk_size;
- break;
+ }
+ break;
default:
/* this should not occur, but in case it does, skip the chunk */
@@ -653,16 +666,9 @@ unknown:
real_parse_index(this);
/* Simple stream selection case - 0/1 audio/video streams */
- if(this->num_video_streams == 1)
- this->video_stream = &this->video_streams[0];
- else
- this->video_stream = NULL;
+ this->video_stream = (this->num_video_streams == 1) ? &this->video_streams[0] : NULL;
+ this->audio_stream = (this->num_audio_streams == 1) ? &this->audio_streams[0] : NULL;
- if(this->num_audio_streams == 1)
- this->audio_stream = &this->audio_streams[0];
- else
- this->audio_stream = NULL;
-
/* In the case of multiple audio/video streams select the first
streams found in the file */
if((this->num_video_streams > 1) || (this->num_audio_streams > 1)) {
@@ -702,15 +708,13 @@ unknown:
while((offset < len) &&
((!this->video_stream && (this->num_video_streams > 0)) ||
(!this->audio_stream && (this->num_audio_streams > 0)))) {
- uint32_t id;
- int i, stream;
+ int i;
/* Check for end of the data chunk */
- if(((id = _X_BE_32(&search_buffer[offset])) == DATA_TAG) ||
- (id == INDX_TAG))
- break;
+ if (is_indx_tag(&search_buffer[offset]) || is_data_tag(&search_buffer[offset]))
+ break;
- stream = _X_BE_16(&search_buffer[offset + 4]);
+ const int stream = _X_BE_16(&search_buffer[offset + 4]);
for(i = 0; !this->video_stream && (i < this->num_video_streams); i++) {
if(stream == this->video_streams[i].mdpr->stream_number) {
@@ -744,14 +748,12 @@ unknown:
/* Send headers and set meta info */
if(this->video_stream) {
- buf_element_t *buf;
-
/* Check for recognised codec*/
if(!this->video_stream->buf_type)
this->video_stream->buf_type = BUF_VIDEO_UNKNOWN;
/* Send header */
- buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
+ buf_element_t *const buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
buf->content = buf->mem;
memcpy(buf->content, this->video_stream->mdpr->type_specific_data,
@@ -784,10 +786,9 @@ unknown:
/* Send headers */
if(this->audio_fifo) {
- mdpr_t *mdpr = this->audio_stream->mdpr;
- buf_element_t *buf;
+ mdpr_t *const mdpr = this->audio_stream->mdpr;
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf_element_t *buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = this->audio_stream->buf_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
@@ -797,7 +798,7 @@ unknown:
* The second is the codec initialisation data found at the end of
* the type specific data for the audio stream */
if(buf->type == BUF_AUDIO_AAC) {
- int version = _X_BE_16(mdpr->type_specific_data + 4);
+ const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4);
if(version != 5) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
@@ -958,9 +959,7 @@ static int demux_real_parse_references(
#define PTS_VIDEO 1
static void check_newpts (demux_real_t *this, int64_t pts, int video, int preview) {
- int64_t diff;
-
- diff = pts - this->last_pts[video];
+ const int64_t diff = pts - this->last_pts[video];
lprintf ("check_newpts %"PRId64"\n", pts);
if (!preview && pts &&
@@ -1066,19 +1065,14 @@ static int demux_real_send_chunk(demux_p
demux_real_t *this = (demux_real_t *) this_gen;
char header[DATA_PACKET_HEADER_SIZE];
- int stream, size, keyframe, input_time = 0;
- unsigned short version;
- uint32_t id, timestamp;
- int64_t pts;
- off_t offset, input_length = 0;
+ int keyframe, input_time = 0;
int normpos = 0;
- read_next_packet:
if(this->reference_mode)
return demux_real_parse_references(this);
/* load a header from wherever the stream happens to be pointing */
- if ( (size=this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE)) !=
+ if ( this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE) !=
DATA_PACKET_HEADER_SIZE) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
@@ -1089,15 +1083,14 @@ static int demux_real_send_chunk(demux_p
}
/* Check to see if we've gone past the end of the data chunk */
- if(((id = _X_BE_32(&header[0])) == DATA_TAG) ||
- (id == INDX_TAG)) {
+ if (is_indx_tag(&header[0]) || is_data_tag(&header[0])) {
lprintf("finished reading data chunk\n");
this->status = DEMUX_FINISHED;
return this->status;
}
/* check version */
- version = _X_BE_16(&header[0]);
+ const uint16_t version = _X_BE_16(&header[0]);
if(version > 1) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: unknown object version in data packet: 0x%04x\n", version);
@@ -1106,11 +1099,11 @@ static int demux_real_send_chunk(demux_p
}
/* read the packet information */
- stream = _X_BE_16(&header[4]);
- offset = this->input->get_current_pos(this->input);
- size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
- timestamp= _X_BE_32(&header[6]);
- pts = (int64_t) timestamp * 90;
+ const uint16_t stream = _X_BE_16(&header[4]);
+ const off_t offset = this->input->get_current_pos(this->input);
+ uint16_t size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
+ const uint32_t timestamp= _X_BE_32(&header[6]);
+ int64_t pts = (int64_t) timestamp * 90;
/* Data packet header with version 1 contains 1 extra byte */
if(version == 0)
@@ -1125,11 +1118,9 @@ static int demux_real_send_chunk(demux_p
if (this->video_stream && (stream == this->video_stream->mdpr->stream_number)) {
- int vpkg_header, vpkg_length, vpkg_offset;
int vpkg_seqnum = -1;
int vpkg_subseq = 0;
buf_element_t *buf;
- int n, fragment_size;
uint32_t decoder_flags;
lprintf ("video chunk detected.\n");
@@ -1144,21 +1135,20 @@ static int demux_real_send_chunk(demux_p
* bit 6: 1=short header (only one block?)
*/
- vpkg_header = stream_read_char (this); size--;
+ const int vpkg_header = stream_read_char (this); size--;
lprintf ("vpkg_hdr: %02x (size=%d)\n", vpkg_header, size);
+ int vpkg_length, vpkg_offset;
if (0x40==(vpkg_header&0xc0)) {
/*
* seems to be a very short header
* 2 bytes, purpose of the second byte yet unknown
*/
- int bummer;
-
- bummer = stream_read_char (this); size--;
+ const int bummer = stream_read_char (this);
lprintf ("bummer == %02X\n",bummer);
vpkg_offset = 0;
- vpkg_length = size;
+ vpkg_length = --size;
} else {
@@ -1219,9 +1209,8 @@ static int demux_real_send_chunk(demux_p
input_time = (int)((int64_t) this->input->get_current_pos(this->input)
* 8 * 1000 / this->avg_bitrate);
- if(this->data_start && this->data_chunk_size)
- input_length = this->data_start + 18 + this->data_chunk_size;
- if( input_length )
+ const off_t input_length = this->data_start + 18 + this->data_chunk_size;
+ if( input_length > 18 )
normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length);
check_newpts (this, pts, PTS_VIDEO, 0);
@@ -1266,13 +1255,17 @@ static int demux_real_send_chunk(demux_p
* calc size of fragment
*/
- if ((vpkg_header & 0xc0) == 0x080)
+ int fragment_size;
+ switch(vpkg_header & 0xc0) {
+ case 0x80:
fragment_size = vpkg_offset;
- else {
- if (0x00 == (vpkg_header&0xc0))
- fragment_size = size;
- else
- fragment_size = vpkg_length;
+ break;
+ case 0x00:
+ fragment_size = size;
+ break;
+ default:
+ fragment_size = vpkg_length;
+ break;
}
lprintf ("fragment size is %d\n", fragment_size);
@@ -1280,14 +1273,11 @@ static int demux_real_send_chunk(demux_p
* read fragment_size bytes of data
*/
- n = fragment_size;
+ int n = fragment_size;
while(n) {
buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
- if(n>buf->max_size)
- buf->size = buf->max_size;
- else
- buf->size = n;
+ buf->size = MIN(n, buf->max_size);
buf->decoder_flags = decoder_flags;
decoder_flags &= ~BUF_FLAG_FRAME_START;
@@ -1371,12 +1361,9 @@ static int demux_real_send_chunk(demux_p
input_time = (int)((int64_t) this->input->get_current_pos(this->input)
* 8 * 1000 / this->avg_bitrate);
- if(this->data_start && this->data_chunk_size)
- input_length = this->data_start + 18 + this->data_chunk_size;
- else
- input_length = 0;
+ const off_t input_length = this->data_start + 18 + this->data_chunk_size;
- if( input_length )
+ if( input_length > 18 )
normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length);
check_newpts (this, pts, PTS_AUDIO, 0);
@@ -1384,13 +1371,14 @@ static int demux_real_send_chunk(demux_p
/* Each packet of AAC is made up of several AAC frames preceded by a
* header defining the size of the frames */
if(this->audio_stream->buf_type == BUF_AUDIO_AAC) {
- int i, frames, *sizes;
+ int i;
/* Upper 4 bits of second byte is frame count */
- frames = (stream_read_word(this) & 0xf0) >> 4;
+ const int frames = (stream_read_word(this) & 0xf0) >> 4;
/* 2 bytes per frame size */
- sizes = calloc(frames, sizeof(int));
+ int sizes[frames];
+
for(i = 0; i < frames; i++)
sizes[i] = stream_read_word(this);
@@ -1402,15 +1390,12 @@ static int demux_real_send_chunk(demux_p
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read AAC frame\n");
- free(sizes);
this->status = DEMUX_FINISHED;
return this->status;
}
pts = 0; /* Only set pts on first frame */
}
-
- free(sizes);
} else if (this->audio_stream->buf_type == BUF_AUDIO_COOK ||
this->audio_stream->buf_type == BUF_AUDIO_ATRK ||
this->audio_stream->buf_type == BUF_AUDIO_28_8 ||
@@ -1508,18 +1493,10 @@ discard:
/* check if it's time to reload */
if (!this->current_data_chunk_packet_count &&
this->next_data_chunk_offset) {
- char preamble[PREAMBLE_SIZE];
unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
/* seek to the next DATA chunk offset */
- this->input->seek(this->input, this->next_data_chunk_offset, SEEK_SET);
-
- /* load the DATA chunk preamble */
- if (this->input->read(this->input, preamble, PREAMBLE_SIZE) !=
- PREAMBLE_SIZE) {
- this->status = DEMUX_FINISHED;
- return this->status;
- }
+ this->input->seek(this->input, this->next_data_chunk_offset + PREAMBLE_SIZE, SEEK_SET);
/* load the rest of the DATA chunk header */
if (this->input->read(this->input, data_chunk_header,
@@ -1658,21 +1635,16 @@ static void demux_real_dispose (demux_pl
for(i = 0; i < this->num_video_streams; i++) {
real_free_mdpr(this->video_streams[i].mdpr);
- if(this->video_streams[i].index)
- free(this->video_streams[i].index);
+ free(this->video_streams[i].index);
}
for(i = 0; i < this->num_audio_streams; i++) {
real_free_mdpr(this->audio_streams[i].mdpr);
- if(this->audio_streams[i].index)
- free(this->audio_streams[i].index);
- if(this->audio_streams[i].frame_buffer)
- free(this->audio_streams[i].frame_buffer);
+ free(this->audio_streams[i].index);
+ free(this->audio_streams[i].frame_buffer);
}
- if(this->fragment_tab)
- free(this->fragment_tab);
-
+ free(this->fragment_tab);
free(this);
}
@@ -1699,21 +1671,27 @@ static int demux_real_get_optional_data(
}
/* help function to discover stream type. returns:
+ * -1 if couldn't read
* 0 if not known.
* 1 if normal stream.
* 2 if reference stream.
*/
-static int real_check_stream_type(uint8_t *buf, int len)
+static int real_check_stream_type(input_plugin_t *input)
{
- if ((buf[0] == 0x2e)
- && (buf[1] == 'R')
- && (buf[2] == 'M')
- && (buf[3] == 'F'))
+ uint8_t buf[1024];
+ off_t len = _x_demux_read_header(input, buf, sizeof(buf));
+
+ if ( len < 4 )
+ return -1;
+
+ if ( memcmp(buf, "\x2eRMF", 4) == 0 )
return 1;
- buf[len] = '\0';
- if( strstr(buf,"pnm://") || strstr(buf,"rtsp://") || strstr(buf,"<smil>") ||
- !strncmp(buf,"http://",7) )
+#define my_strnstr(haystack, haystacklen, needle) \
+ memmem(haystack, haystacklen, needle, sizeof(needle))
+
+ if( my_strnstr(buf, len, "pnm://") || my_strnstr(buf, len, "rtsp://") ||
+ my_strnstr(buf, len, "<smil>") || !strncmp(buf, "http://", MIN(7, len)) )
return 2;
return 0;
@@ -1722,32 +1700,24 @@ static demux_plugin_t *open_plugin (demu
static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream,
input_plugin_t *input) {
- demux_real_t *this;
- uint8_t buf[1024+1];
- int len, stream_type=0;
+ /* discover stream type */
+ const int stream_type = real_check_stream_type(input);
+
+ if ( stream_type < 0 )
+ return NULL;
switch (stream->content_detection_method) {
- case METHOD_BY_CONTENT:{
-
- if (! (len = _x_demux_read_header(input, buf, 1024)) )
+ case METHOD_BY_CONTENT:
+ if ( stream_type < 1 )
return NULL;
-
- lprintf ("read 4 bytes: %02x %02x %02x %02x\n",
- buf[0], buf[1], buf[2], buf[3]);
-
- if (!(stream_type = real_check_stream_type(buf,len)))
- return NULL;
- }
-
- lprintf ("by content accepted.\n");
- break;
+
+ lprintf ("by content accepted.\n");
+ break;
case METHOD_BY_EXTENSION: {
- const char *extensions, *mrl;
-
- mrl = input->get_mrl (input);
- extensions = class_gen->get_extensions (class_gen);
+ const char *const mrl = input->get_mrl (input);
+ const char *const extensions = class_gen->get_extensions (class_gen);
lprintf ("by extension '%s'\n", mrl);
@@ -1766,16 +1736,10 @@ static demux_plugin_t *open_plugin (demu
return NULL;
}
-
- this = calloc(1, sizeof(demux_real_t));
+ demux_real_t *this = calloc(1, sizeof(demux_real_t));
this->stream = stream;
this->input = input;
-
- /* discover stream type */
- if(!stream_type)
- if ( (len = _x_demux_read_header(this->input, buf, 1024)) )
- stream_type = real_check_stream_type(buf,len);
if(stream_type == 2){
this->reference_mode = 1;
@@ -1823,9 +1787,7 @@ static void class_dispose (demux_class_t
}
static void *init_class (xine_t *xine, void *data) {
- demux_real_class_t *this;
-
- this = calloc(1, sizeof(demux_real_class_t));
+ demux_real_class_t *const this = calloc(1, sizeof(demux_real_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c
--- a/src/demuxers/demux_realaudio.c
+++ b/src/demuxers/demux_realaudio.c
@@ -64,7 +64,9 @@ typedef struct {
off_t data_start;
off_t data_size;
- int sps, cfs, w, h;
+ uint32_t cfs;
+ uint16_t w, h;
+ int frame_len;
size_t frame_size;
uint8_t *frame_buffer;
@@ -77,27 +79,22 @@ typedef struct {
} demux_ra_class_t;
/* Map flavour to bytes per second */
-static int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second
+static const int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second
/* returns 1 if the RealAudio file was opened successfully, 0 otherwise */
static int open_ra_file(demux_ra_t *this) {
- unsigned char file_header[RA_FILE_HEADER_PREV_SIZE], len;
- unsigned short version;
- off_t offset;
-
+ uint8_t file_header[RA_FILE_HEADER_PREV_SIZE];
/* check the signature */
if (_x_demux_read_header(this->input, file_header, RA_FILE_HEADER_PREV_SIZE) !=
RA_FILE_HEADER_PREV_SIZE)
return 0;
- if ((file_header[0] != '.') ||
- (file_header[1] != 'r') ||
- (file_header[2] != 'a'))
+ if ( memcmp(file_header, ".ra", 3) != 0 )
return 0;
/* read version */
- version = _X_BE_16(&file_header[0x04]);
+ const uint16_t version = _X_BE_16(&file_header[0x04]);
/* read header size according to version */
if (version == 3)
@@ -118,6 +115,7 @@ static int open_ra_file(demux_ra_t *this
return 0;
}
+ off_t offset;
/* read header data according to version */
if((version == 3) && (this->header_size >= 32)) {
this->data_size = _X_BE_32(&this->header[0x12]);
@@ -147,31 +145,37 @@ static int open_ra_file(demux_ra_t *this
}
/* Read title */
- len = this->header[offset];
- if(len && ((offset+len+2) < this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len+2) < this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
/* Author */
- len = this->header[offset];
- if(len && ((offset+len+1) < this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len+1) < this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
/* Copyright/Date */
- len = this->header[offset];
- if(len && ((offset+len) <= this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len) <= this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
/* Fourcc for version 3 comes after meta info */
if(version == 3) {
@@ -193,16 +197,23 @@ static int open_ra_file(demux_ra_t *this
this->audio_type = _x_formattag_to_buf_audio(this->fourcc);
if (version == 4) {
- this->sps = _X_BE_16 (this->header+44);
+ const uint16_t sps = _X_BE_16 (this->header+44) ? : 1;
this->w = _X_BE_16 (this->header+42);
this->h = _X_BE_16 (this->header+40);
this->cfs = _X_BE_32 (this->header+24);
- if (this->sps) {
- this->frame_size = this->sps * this->h * this->sps;
- this->frame_buffer = xine_xmalloc (this->frame_size);
- } else {
- this->frame_size = this->w * this->h;
- this->frame_buffer = xine_xmalloc (this->frame_size);
+
+ if (this->w < 0x8000 && this->h < 0x8000) {
+ uint64_t fs;
+ this->frame_len = this->w * this->h;
+ fs = (uint64_t) this->frame_len * sps;
+ if (fs < 0x80000000) {
+ this->frame_size = fs;
+ this->frame_buffer = calloc(this->frame_size, 1);
+ }
+ }
+ if (! this->frame_buffer) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: malloc failed\n");
+ return 0;
}
if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO)
@@ -227,7 +238,6 @@ static int demux_ra_send_chunk(demux_plu
demux_ra_t *this = (demux_ra_t *) this_gen;
off_t current_normpos = 0;
- int64_t current_pts;
/* just load data chunks from wherever the stream happens to be
* pointing; issue a DEMUX_FINISHED status if EOF is reached */
@@ -235,7 +245,7 @@ static int demux_ra_send_chunk(demux_plu
current_normpos = (int)( (double) (this->input->get_current_pos (this->input) - this->data_start) *
65535 / this->data_size );
- current_pts = 0; /* let the engine sort out the pts for now */
+ const int64_t current_pts = 0; /* let the engine sort out the pts for now */
if (this->seek_flag) {
_x_demux_control_newpts(this->stream, current_pts, BUF_FLAG_SEEK);
@@ -243,26 +253,21 @@ static int demux_ra_send_chunk(demux_plu
}
if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) {
- uint8_t * buffer;
-
- buffer = this->frame_buffer;
if (this->audio_type == BUF_AUDIO_SIPRO) {
- int len = this->h * this->w;
- if(this->input->read(this->input, this->frame_buffer, len) < len) {
+ if(this->input->read(this->input, this->frame_buffer, this->frame_len) < this->frame_len) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_realaudio: failed to read audio chunk\n");
this->status = DEMUX_FINISHED;
return this->status;
}
- demux_real_sipro_swap (this->frame_buffer, len * 2 / 96);
+ demux_real_sipro_swap (this->frame_buffer, this->frame_len * 2 / 96);
} else {
int x, y;
- int pos;
for (y = 0; y < this->h; y++)
for (x = 0; x < this->h / 2; x++) {
- pos = x * 2 * this->w + y * this->cfs;
+ const int pos = x * 2 * this->w + y * this->cfs;
if(this->input->read(this->input, this->frame_buffer + pos,
this->cfs) < this->cfs) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
@@ -275,7 +280,7 @@ static int demux_ra_send_chunk(demux_plu
}
_x_demux_send_data(this->audio_fifo,
- buffer, this->frame_size,
+ this->frame_buffer, this->frame_size,
current_pts, this->audio_type, 0,
current_normpos, current_pts / 90, 0, 0);
} else if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align,
@@ -310,10 +315,7 @@ static void demux_ra_send_headers(demux_
buf->type = this->audio_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
- if(this->header_size > buf->max_size)
- buf->size = buf->max_size;
- else
- buf->size = this->header_size;
+ buf->size = MIN(this->header_size, buf->max_size);
memcpy(buf->content, this->header, buf->size);
diff --git a/src/demuxers/demux_shn.c b/src/demuxers/demux_shn.c
--- a/src/demuxers/demux_shn.c
+++ b/src/demuxers/demux_shn.c
@@ -88,7 +88,7 @@ static int demux_shn_send_chunk(demux_pl
buf->pts = 0;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_slave.c b/src/demuxers/demux_slave.c
--- a/src/demuxers/demux_slave.c
+++ b/src/demuxers/demux_slave.c
@@ -90,10 +90,11 @@ static int demux_slave_next (demux_slave
/* fill the scratch buffer */
n = this->input->read(this->input, &this->scratch[this->scratch_used],
SCRATCH_SIZE - this->scratch_used);
- this->scratch_used += n;
+ if (n > 0)
+ this->scratch_used += n;
this->scratch[this->scratch_used] = '\0';
- if( !n ) {
+ if (n <= 0) {
lprintf("connection closed\n");
this->status = DEMUX_FINISHED;
return 0;
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -1573,7 +1573,7 @@ static unsigned char * demux_synchronise
do {
read_length = this->input->read(this->input, this->buf,
PKT_SIZE * NPKT_PER_READ);
- if (read_length % PKT_SIZE) {
+ if (read_length < 0 || read_length % PKT_SIZE) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: read returned %d bytes (not a multiple of %d!)\n",
read_length, PKT_SIZE);
diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c
--- a/src/demuxers/demux_tta.c
+++ b/src/demuxers/demux_tta.c
@@ -126,6 +126,10 @@ static int demux_tta_send_chunk(demux_pl
/* buf->extra_info->input_time = this->current_sample / this->samplerate; */
bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read);
+ if (bytes_read < 0) {
+ this->status = DEMUX_FINISHED;
+ break;
+ }
buf->size = bytes_read;
diff --git a/src/demuxers/demux_vox.c b/src/demuxers/demux_vox.c
--- a/src/demuxers/demux_vox.c
+++ b/src/demuxers/demux_vox.c
@@ -77,7 +77,7 @@ static int demux_vox_send_chunk (demux_p
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_DIALOGIC_IMA;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
diff --git a/src/demuxers/demux_yuv_frames.c b/src/demuxers/demux_yuv_frames.c
--- a/src/demuxers/demux_yuv_frames.c
+++ b/src/demuxers/demux_yuv_frames.c
@@ -129,13 +129,19 @@ static void demux_yuv_frames_send_header
if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO)) {
buf = this->input->read_block(this->input, this->audio_fifo, 0);
- this->audio_fifo->put(this->audio_fifo, buf);
+ if (buf)
+ this->audio_fifo->put(this->audio_fifo, buf);
+ else
+ this->status = DEMUX_FINISHED;
}
if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO)) {
buf = this->input->read_block(this->input, this->video_fifo, 0);
- this->video_fifo->put(this->video_fifo, buf);
+ if (buf)
+ this->video_fifo->put(this->video_fifo, buf);
+ else
+ this->status = DEMUX_FINISHED;
}
this->status = DEMUX_OK;
diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c
--- a/src/input/input_dvb.c
+++ b/src/input/input_dvb.c
@@ -2601,6 +2601,10 @@ static buf_element_t *dvb_plugin_read_bl
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
int total_bytes;
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c
--- a/src/input/input_dvd.c
+++ b/src/input/input_dvd.c
@@ -849,6 +849,9 @@ static buf_element_t *dvd_plugin_read_bl
static off_t dvd_plugin_read (input_plugin_t *this_gen, char *ch_buf, off_t len) {
/* dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; */
+
+ if (len < 4)
+ return -1;
/* FIXME: Tricking the demux_mpeg_block plugin */
ch_buf[0] = 0;
diff --git a/src/input/input_file.c b/src/input/input_file.c
--- a/src/input/input_file.c
+++ b/src/input/input_file.c
@@ -145,6 +145,9 @@ static off_t file_plugin_read (input_plu
static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) {
file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
+ if (len < 0)
+ return -1;
+
#ifdef HAVE_MMAP
if ( check_mmap_file(this) ) {
off_t l = len;
@@ -165,6 +168,11 @@ static buf_element_t *file_plugin_read_b
file_input_plugin_t *this = (file_input_plugin_t *) this_gen;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c
--- a/src/input/input_gnome_vfs.c
+++ b/src/input/input_gnome_vfs.c
@@ -120,6 +120,11 @@ gnomevfs_plugin_read_block (input_plugin
{
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_http.c b/src/input/input_http.c
--- a/src/input/input_http.c
+++ b/src/input/input_http.c
@@ -421,6 +421,9 @@ static off_t http_plugin_read (input_plu
num_bytes = 0;
+ if (nlen < 0)
+ return -1;
+
if (this->curpos < this->preview_size) {
if (nlen > (this->preview_size - this->curpos))
@@ -437,7 +440,7 @@ static off_t http_plugin_read (input_plu
n = nlen - num_bytes;
- if (n) {
+ if (n > 0) {
int read_bytes;
read_bytes = http_plugin_read_int (this, &buf[num_bytes], n);
@@ -503,6 +506,11 @@ static buf_element_t *http_plugin_read_b
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
+
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -554,7 +562,7 @@ static off_t http_plugin_seek(input_plug
if ((origin == SEEK_CUR) && (offset >= 0)) {
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
@@ -576,7 +584,7 @@ static off_t http_plugin_seek(input_plug
offset -= this->curpos;
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
@@ -996,6 +1004,7 @@ static int http_plugin_open (input_plugi
this->preview_size = http_plugin_read_int (this, this->preview, MAX_PREVIEW_SIZE);
}
if (this->preview_size < 0) {
+ this->preview_size = 0;
xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: read error %d\n"), errno);
return -12;
}
diff --git a/src/input/input_mms.c b/src/input/input_mms.c
--- a/src/input/input_mms.c
+++ b/src/input/input_mms.c
@@ -121,6 +121,11 @@ static buf_element_t *mms_plugin_read_bl
int total_bytes;
lprintf ("mms_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_net.c b/src/input/input_net.c
--- a/src/input/input_net.c
+++ b/src/input/input_net.c
@@ -253,6 +253,9 @@ static off_t net_plugin_read (input_plug
lprintf("reading %" PRIdMAX " bytes...\n", (intmax_t)len);
+ if (len < 0)
+ return -1;
+
total=0;
if (this->curpos < this->preview_size) {
n = this->preview_size - this->curpos;
@@ -287,6 +290,11 @@ static buf_element_t *net_plugin_read_bl
/* net_input_plugin_t *this = (net_input_plugin_t *) this_gen; */
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
off_t total_bytes;
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -331,7 +339,7 @@ static off_t net_plugin_seek (input_plug
if ((origin == SEEK_CUR) && (offset >= 0)) {
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
@@ -353,7 +361,7 @@ static off_t net_plugin_seek (input_plug
offset -= this->curpos;
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c
--- a/src/input/input_pnm.c
+++ b/src/input/input_pnm.c
@@ -83,7 +83,8 @@ static off_t pnm_plugin_read (input_plug
lprintf ("pnm_plugin_read: %"PRId64" bytes ...\n", len);
n = pnm_read (this->pnm, buf, len);
- this->curpos += n;
+ if (n >= 0)
+ this->curpos += n;
return n;
}
@@ -95,6 +96,11 @@ static buf_element_t *pnm_plugin_read_bl
int total_bytes;
lprintf ("pnm_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -123,10 +129,16 @@ static off_t pnm_plugin_seek (input_plug
if ((origin == SEEK_CUR) && (offset >= 0)) {
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- this->curpos += pnm_plugin_read (this_gen, this->scratch, BUFSIZE);
+ off_t n = pnm_plugin_read (this_gen, this->scratch, BUFSIZE);
+ if (n <= 0)
+ return this->curpos;
+ this->curpos += n;
}
- this->curpos += pnm_plugin_read (this_gen, this->scratch, offset);
+ off_t n = pnm_plugin_read (this_gen, this->scratch, offset);
+ if (n <= 0)
+ return this->curpos;
+ this->curpos += n;
}
return this->curpos;
diff --git a/src/input/input_pvr.c b/src/input/input_pvr.c
--- a/src/input/input_pvr.c
+++ b/src/input/input_pvr.c
@@ -423,6 +423,9 @@ static uint32_t pvr_plugin_get_capabilit
static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) {
/*pvr_input_plugin_t *this = (pvr_input_plugin_t *) this_gen;*/
+
+ if (len < 4)
+ return -1;
/* FIXME: Tricking the demux_mpeg_block plugin */
buf[0] = 0;
@@ -1199,6 +1202,9 @@ static buf_element_t *pvr_plugin_read_bl
buf_element_t *buf;
int speed = _x_get_speed(this->stream);
+ if (todo < 0 || todo > buf->size)
+ return NULL;
+
if( !this->pvr_running ) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: thread died, aborting\n");
return NULL;
diff --git a/src/input/input_rtp.c b/src/input/input_rtp.c
--- a/src/input/input_rtp.c
+++ b/src/input/input_rtp.c
@@ -453,6 +453,9 @@ static off_t rtp_plugin_read (input_plug
struct timespec timeout;
off_t copied = 0;
+ if (length < 0)
+ return -1;
+
while(length > 0) {
off_t n;
@@ -524,6 +527,10 @@ static buf_element_t *rtp_plugin_read_bl
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
int total_bytes;
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -609,11 +616,14 @@ static int rtp_plugin_get_optional_data
if (data_type == INPUT_OPTIONAL_DATA_PREVIEW) {
if (!this->preview_read_done) {
this->preview_size = rtp_plugin_read(this_gen, this->preview, MAX_PREVIEW_SIZE);
+ if (this->preview_size < 0)
+ this->preview_size = 0;
lprintf("Preview data length = %d\n", this->preview_size);
this->preview_read_done = 1;
}
- memcpy(data, this->preview, this->preview_size);
+ if (this->preview_size)
+ memcpy(data, this->preview, this->preview_size);
return this->preview_size;
}
else {
diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c
--- a/src/input/input_rtsp.c
+++ b/src/input/input_rtsp.c
@@ -84,7 +84,8 @@ static off_t rtsp_plugin_read (input_plu
lprintf ("rtsp_plugin_read: %"PRId64" bytes ...\n", len);
n = rtsp_session_read (this->rtsp, buf, len);
- this->curpos += n;
+ if (n > 0)
+ this->curpos += n;
return n;
}
@@ -96,6 +97,11 @@ static buf_element_t *rtsp_plugin_read_b
int total_bytes;
lprintf ("rtsp_plugin_read_block: %"PRId64" bytes...\n", todo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -123,10 +129,16 @@ static off_t rtsp_plugin_seek (input_plu
if ((origin == SEEK_CUR) && (offset >= 0)) {
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE);
+ off_t n = rtsp_plugin_read (this_gen, this->scratch, BUFSIZE);
+ if (n <= 0)
+ return this->curpos;
+ this->curpos += n;
}
- this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset);
+ off_t n = rtsp_plugin_read (this_gen, this->scratch, offset);
+ if (n <= 0)
+ return this->curpos;
+ this->curpos += n;
}
return this->curpos;
diff --git a/src/input/input_smb.c b/src/input/input_smb.c
--- a/src/input/input_smb.c
+++ b/src/input/input_smb.c
@@ -69,6 +69,8 @@ smb_plugin_read (input_plugin_t *this_ge
smb_input_t *this = (smb_input_t *) this_gen;
off_t n, num_bytes;
+ if (len < 0)
+ return -1;
num_bytes = 0;
while (num_bytes < len)
@@ -88,6 +90,11 @@ smb_plugin_read_block (input_plugin_t *t
{
off_t total_bytes;
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c
--- a/src/input/input_stdin_fifo.c
+++ b/src/input/input_stdin_fifo.c
@@ -85,6 +85,8 @@ static off_t stdin_plugin_read (input_pl
off_t n, total;
lprintf ("reading %"PRId64" bytes...\n", len);
+ if (len < 0)
+ return -1;
total=0;
if (this->curpos < this->preview_size) {
@@ -121,6 +123,11 @@ static buf_element_t *stdin_plugin_read_
/* stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; */
buf_element_t *buf = fifo->buffer_pool_alloc (fifo);
+ if (todo < 0 || todo > buf->size) {
+ buf->free_buffer (buf);
+ return NULL;
+ }
+
buf->content = buf->mem;
buf->type = BUF_DEMUX_BLOCK;
@@ -146,7 +153,7 @@ static off_t stdin_plugin_seek (input_pl
if ((origin == SEEK_CUR) && (offset >= 0)) {
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
@@ -168,7 +175,7 @@ static off_t stdin_plugin_seek (input_pl
offset -= this->curpos;
for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) {
- if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) )
+ if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 )
return this->curpos;
}
@@ -270,6 +277,8 @@ static int stdin_plugin_open (input_plug
this->preview_size = stdin_plugin_read (&this->input_plugin, this->preview,
MAX_PREVIEW_SIZE);
+ if (this->preview_size < 0)
+ this->preview_size = 0;
this->curpos = 0;
return 1;
diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c
--- a/src/libsputext/demux_sputext.c
+++ b/src/libsputext/demux_sputext.c
@@ -149,7 +149,7 @@ static char *read_line_from_input(demux_
char *s;
int linelen;
- if ((len - this->buflen) > 512) {
+ if ((len - this->buflen) > 512 && len < SUB_BUFSIZE) {
if((nread = this->input->read(this->input,
&this->buf[this->buflen], len - this->buflen)) < 0) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "read failed.\n");
diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h
--- a/src/video_out/xxmc.h
+++ b/src/video_out/xxmc.h
@@ -36,6 +36,14 @@
#define _XXMC_H
#define XVMC_THREAD_SAFE
+
+/*
+ * some implementations are not aware of the display having been locked
+ * already before calling the xvmc function and may therefore deadlock.
+ */
+/*
+#define XVMC_LOCKDISPLAY_SAFE
+*/
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -171,7 +179,7 @@ typedef struct context_lock_s {
return; \
}
-#ifdef XVMC_THREAD_SAFE
+#if defined(XVMC_THREAD_SAFE) && defined(XVMC_LOCKDISPLAY_SAFE)
#define XVMCLOCKDISPLAY(display)
#define XVMCUNLOCKDISPLAY(display)
#else
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -138,6 +138,28 @@ void _x_demux_control_newpts( xine_strea
pthread_mutex_unlock(&stream->demux_mutex);
}
+/* avoid ao_loop being stuck in a pthread_cond_wait, waiting for data;
+ * return 1 if the stream is stopped
+ * (better fix wanted!)
+ */
+static int demux_unstick_ao_loop (xine_stream_t *stream)
+{
+ if (!stream->audio_thread_created)
+ return 0;
+
+ int status = xine_get_status (stream);
+ if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP)
+ return 0;
+
+ /* right, stream is stopped... */
+ audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out);
+ buf->num_frames = 0;
+ buf->stream = NULL;
+ stream->audio_out->put_buffer (stream->audio_out, buf, stream);
+
+ return 1;
+}
+
/* sync with decoder fifos, making sure everything gets processed */
void _x_demux_control_headers_done (xine_stream_t *stream) {
@@ -190,6 +212,9 @@ void _x_demux_control_headers_done (xine
ts.tv_nsec = tv.tv_usec * 1000;
/* use timedwait to workaround buggy pthread broadcast implementations */
pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts);
+
+ if (demux_unstick_ao_loop (stream))
+ break;
}
stream->demux_action_pending = 0;
@@ -347,6 +372,9 @@ static void *demux_loop (void *stream_ge
(stream->finished_count_video < finished_count_video)) {
lprintf ("waiting for finisheds.\n");
pthread_cond_wait (&stream->counter_changed, &stream->counter_lock);
+
+ if (demux_unstick_ao_loop (stream))
+ break;
}
pthread_mutex_unlock (&stream->counter_lock);
Attachment:
pgp_lju9S39HE.pgp
Description: PGP signature