diff options
Diffstat (limited to 'src/demuxers/demux_real.c')
-rw-r--r-- | src/demuxers/demux_real.c | 88 |
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, |