From: Darren S. <li...@yo...> - 2009-01-18 16:06:15
|
# HG changeset patch # User Darren Salt <li...@yo...> # Date 1232291432 0 # Node ID 071dc93156e6940a7f1b8bb38762d521dd5731e8 # Parent aed53c8313f0d3cb91073bc61e45000133444c91 Add allocation checks to the Real MDPR parsing code (ref. CVE-2008-5240). diff -r 071dc93156e6940a7f1b8bb38762d521dd5731e8 -r aed53c8313f0d3cb91073bc61e45000133444c91 src/demuxers/demux_real.c --- a/src/demuxers/demux_real.c Sun Jan 18 15:10:32 2009 +0000 +++ b/src/demuxers/demux_real.c Sun Jan 18 02:31:06 2009 +0000 @@ -265,8 +265,12 @@ static void real_parse_index(demux_real_ 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 +282,29 @@ static mdpr_t *real_parse_mdpr(const cha 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 +324,13 @@ static mdpr_t *real_parse_mdpr(const cha #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) { @@ -491,9 +514,14 @@ static void real_parse_headers (demux_re 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"); diff -r 071dc93156e6940a7f1b8bb38762d521dd5731e8 -r aed53c8313f0d3cb91073bc61e45000133444c91 src/input/libreal/rmff.c --- a/src/input/libreal/rmff.c Sun Jan 18 15:10:32 2009 +0000 +++ b/src/input/libreal/rmff.c Sun Jan 18 02:31:06 2009 +0000 @@ -334,12 +334,14 @@ static rmff_prop_t *rmff_scan_prop(const return prop; } -static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { - - rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t)); +static rmff_mdpr_t *rmff_scan_mdpr(const char *data) +{ + rmff_mdpr_t *mdpr = calloc(sizeof(rmff_mdpr_t), 1); mdpr->object_id=_X_BE_32(data); mdpr->size=_X_BE_32(&data[4]); + if (mdpr->size < 46) + goto fail; mdpr->object_version=_X_BE_16(&data[8]); if (mdpr->object_version != 0) { @@ -355,21 +357,40 @@ static rmff_mdpr_t *rmff_scan_mdpr(const mdpr->duration=_X_BE_32(&data[36]); mdpr->stream_name_size=data[40]; + if (mdpr->size < 46 + 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[41], mdpr->stream_name_size); mdpr->stream_name[mdpr->stream_name_size]=0; mdpr->mime_type_size=data[41+mdpr->stream_name_size]; + if (mdpr->size < 46 + 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[42+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[mdpr->mime_type_size]=0; mdpr->type_specific_len=_X_BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]); + if (mdpr->size < 46 + 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[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); return mdpr; + +fail: + free (mdpr->stream_name); + free (mdpr->mime_type); + free (mdpr->type_specific_data); + free (mdpr); + return NULL; } static rmff_cont_t *rmff_scan_cont(const char *data) { @@ -467,8 +488,11 @@ rmff_header_t *rmff_scan_header(const ch break; case MDPR_TAG: mdpr=rmff_scan_mdpr(ptr); - chunk_size=mdpr->size; - header->streams[mdpr->stream_number]=mdpr; + if (mdpr) /* FIXME: what to do if NULL? */ + { + chunk_size=mdpr->size; + header->streams[mdpr->stream_number]=mdpr; + } break; case CONT_TAG: header->cont=rmff_scan_cont(ptr); |