summaryrefslogtreecommitdiff
path: root/src/demuxers/demux_real.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers/demux_real.c')
-rw-r--r--src/demuxers/demux_real.c88
1 files changed, 70 insertions, 18 deletions
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index aa4dfc26b..774c74e2c 100644
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -42,6 +42,9 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#define LOG_MODULE "demux_real"
#define LOG_VERBOSE
@@ -265,8 +268,12 @@ static void real_parse_index(demux_real_t *this) {
this->input->seek(this->input, original_pos, SEEK_SET);
}
-static mdpr_t *real_parse_mdpr(const char *data) {
- mdpr_t *mdpr=malloc(sizeof(mdpr_t));
+static mdpr_t *real_parse_mdpr(const char *data, const unsigned int size)
+{
+ if (size < 38)
+ return NULL;
+
+ mdpr_t *mdpr=calloc(sizeof(mdpr_t), 1);
mdpr->stream_number=_X_BE_16(&data[2]);
mdpr->max_bit_rate=_X_BE_32(&data[4]);
@@ -278,17 +285,29 @@ static mdpr_t *real_parse_mdpr(const char *data) {
mdpr->duration=_X_BE_32(&data[28]);
mdpr->stream_name_size=data[32];
+ if (size < 38 + mdpr->stream_name_size)
+ goto fail;
mdpr->stream_name=malloc(mdpr->stream_name_size+1);
+ if (!mdpr->stream_name)
+ goto fail;
memcpy(mdpr->stream_name, &data[33], mdpr->stream_name_size);
mdpr->stream_name[(int)mdpr->stream_name_size]=0;
mdpr->mime_type_size=data[33+mdpr->stream_name_size];
+ if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size)
+ goto fail;
mdpr->mime_type=malloc(mdpr->mime_type_size+1);
+ if (!mdpr->mime_type)
+ goto fail;
memcpy(mdpr->mime_type, &data[34+mdpr->stream_name_size], mdpr->mime_type_size);
mdpr->mime_type[(int)mdpr->mime_type_size]=0;
mdpr->type_specific_len=_X_BE_32(&data[34+mdpr->stream_name_size+mdpr->mime_type_size]);
+ if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data)
+ goto fail;
mdpr->type_specific_data=malloc(mdpr->type_specific_len);
+ if (!mdpr->type_specific_data)
+ goto fail;
memcpy(mdpr->type_specific_data,
&data[38+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len);
@@ -308,6 +327,13 @@ static mdpr_t *real_parse_mdpr(const char *data) {
#endif
return mdpr;
+
+fail:
+ free (mdpr->stream_name);
+ free (mdpr->mime_type);
+ free (mdpr->type_specific_data);
+ free (mdpr);
+ return NULL;
}
static void real_free_mdpr (mdpr_t *mdpr) {
@@ -318,9 +344,15 @@ 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)
+ real_stream_t * stream)
{
+ 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;
+ }
+
+ 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);
@@ -359,9 +391,14 @@ static void real_parse_audio_specific_data (demux_real_t *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?
*/
- stream->frame_size = stream->w * stream->h;
+ 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 = 0;
+ stream->frame_buffer = NULL;
+ }
- stream->frame_buffer = calloc(stream->frame_size, 1);
stream->frame_num_bytes = 0;
stream->sub_packet_cnt = 0;
@@ -430,9 +467,14 @@ static void real_parse_headers (demux_real_t *this) {
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 (this->input->read(this->input, chunk_buffer, chunk_size) !=
+ if (! chunk_buffer ||
+ this->input->read(this->input, chunk_buffer, chunk_size) !=
chunk_size) {
free (chunk_buffer);
this->status = DEMUX_FINISHED;
@@ -475,9 +517,14 @@ static void real_parse_headers (demux_real_t *this) {
continue;
}
- mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer);
+ mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer, chunk_size);
lprintf ("parsing type specific data...\n");
+ if (!mdpr) {
+ free (chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) {
lprintf ("mpeg layer 3 audio detected...\n");
@@ -487,7 +534,8 @@ static void real_parse_headers (demux_real_t *this) {
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) {
+ } 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");
@@ -498,26 +546,30 @@ static void real_parse_headers (demux_real_t *this) {
lprintf("audio version %d detected\n", version);
- char *fourcc_ptr = NULL;
+ 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_ptr = 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: {
- const uint8_t len = *(mdpr->type_specific_data + 56);
- fourcc_ptr = mdpr->type_specific_data + 58 + len;
+ 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_ptr = 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);
const uint32_t fourcc = _X_ME_32(fourcc_ptr);
@@ -528,11 +580,11 @@ static void real_parse_headers (demux_real_t *this) {
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);
+ &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,