[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xine-lib 1.1.14-4 uploaded to t-p-u



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


Reply to: