X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fasfdec_f.c;h=27162e95590d88d00aedd3248fa4503fd1bb1582;hb=8b3e6ce5f4ab1ebf3a54ff7e0ff440a1a5f842f7;hp=64a0b9d7f2ae11ff144b4e2dc78540002e4b81f7;hpb=94346ab593f3fc0822f11d3e3f378f9944ad2d40;p=ffmpeg diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c index 64a0b9d7f2a..27162e95590 100644 --- a/libavformat/asfdec_f.c +++ b/libavformat/asfdec_f.c @@ -33,7 +33,6 @@ #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" -#include "id3v2.h" #include "internal.h" #include "riff.h" #include "asf.h" @@ -143,6 +142,12 @@ static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */ 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 }; +static const ff_asf_guid asf_audio_conceal_none = { + // 0x40, 0xa4, 0xf1, 0x49, 0x4ece, 0x11d0, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 + // New value lifted from avifile + 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b +}; + #define PRINT_IF_GUID(g, cmp) \ if (!ff_guidcmp(g, &cmp)) \ av_log(NULL, AV_LOG_TRACE, "(GUID: %s) ", # cmp) @@ -154,7 +159,7 @@ static void print_guid(ff_asf_guid *g) else PRINT_IF_GUID(g, ff_asf_file_header); else PRINT_IF_GUID(g, ff_asf_stream_header); else PRINT_IF_GUID(g, ff_asf_audio_stream); - else PRINT_IF_GUID(g, ff_asf_audio_conceal_none); + else PRINT_IF_GUID(g, asf_audio_conceal_none); else PRINT_IF_GUID(g, ff_asf_video_stream); else PRINT_IF_GUID(g, ff_asf_video_conceal_none); else PRINT_IF_GUID(g, ff_asf_command_stream); @@ -186,7 +191,7 @@ static void print_guid(ff_asf_guid *g) #define print_guid(g) while(0) #endif -static int asf_probe(AVProbeData *pd) +static int asf_probe(const AVProbeData *pd) { /* check file header */ if (!ff_guidcmp(pd->buf, &ff_asf_header)) @@ -213,107 +218,6 @@ static int get_value(AVIOContext *pb, int type, int type2_size) } } -/* MSDN claims that this should be "compatible with the ID3 frame, APIC", - * but in reality this is only loosely similar */ -static int asf_read_picture(AVFormatContext *s, int len) -{ - AVPacket pkt = { 0 }; - const CodecMime *mime = ff_id3v2_mime_tags; - enum AVCodecID id = AV_CODEC_ID_NONE; - char mimetype[64]; - uint8_t *desc = NULL; - AVStream *st = NULL; - int ret, type, picsize, desc_len; - - /* type + picsize + mime + desc */ - if (len < 1 + 4 + 2 + 2) { - av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); - return AVERROR_INVALIDDATA; - } - - /* picture type */ - type = avio_r8(s->pb); - len--; - if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { - av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type); - type = 0; - } - - /* picture data size */ - picsize = avio_rl32(s->pb); - len -= 4; - - /* picture MIME type */ - len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype)); - while (mime->id != AV_CODEC_ID_NONE) { - if (!strncmp(mime->str, mimetype, sizeof(mimetype))) { - id = mime->id; - break; - } - mime++; - } - if (id == AV_CODEC_ID_NONE) { - av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", - mimetype); - return 0; - } - - if (picsize >= len) { - av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n", - picsize, len); - return AVERROR_INVALIDDATA; - } - - /* picture description */ - desc_len = (len - picsize) * 2 + 1; - desc = av_malloc(desc_len); - if (!desc) - return AVERROR(ENOMEM); - len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len); - - ret = av_get_packet(s->pb, &pkt, picsize); - if (ret < 0) - goto fail; - - st = avformat_new_stream(s, NULL); - if (!st) { - ret = AVERROR(ENOMEM); - goto fail; - } - st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - st->codecpar->codec_id = id; - st->attached_pic = pkt; - st->attached_pic.stream_index = st->index; - st->attached_pic.flags |= AV_PKT_FLAG_KEY; - - if (*desc) - av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); - else - av_freep(&desc); - - av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0); - - return 0; - -fail: - av_freep(&desc); - av_packet_unref(&pkt); - return ret; -} - -static void get_id3_tag(AVFormatContext *s, int len) -{ - ID3v2ExtraMeta *id3v2_extra_meta = NULL; - - ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); - if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, &id3v2_extra_meta); - ff_id3v2_parse_chapters(s, &id3v2_extra_meta); - } - ff_id3v2_free_extra_meta(&id3v2_extra_meta); -} - static void get_tag(AVFormatContext *s, const char *key, int type, int len, int type2_size) { ASFContext *asf = s->priv_data; @@ -321,8 +225,7 @@ static void get_tag(AVFormatContext *s, const char *key, int type, int len, int int64_t off = avio_tell(s->pb); #define LEN 22 - if ((unsigned)len >= (UINT_MAX - LEN) / 2) - return; + av_assert0((unsigned)len < (INT_MAX - LEN) / 2); if (!asf->export_xmp && !strncmp(key, "xmp", 3)) goto finish; @@ -340,13 +243,8 @@ static void get_tag(AVFormatContext *s, const char *key, int type, int len, int value[len]=0; break; case ASF_BYTE_ARRAY: - if (!strcmp(key, "WM/Picture")) { // handle cover art - asf_read_picture(s, len); - } else if (!strcmp(key, "ID3")) { // handle ID3 tag - get_id3_tag(s, len); - } else { + if (ff_asf_handle_byte_array(s, key, len) > 0) av_log(s, AV_LOG_VERBOSE, "Unsupported byte array in tag %s.\n", key); - } goto finish; case ASF_BOOL: case ASF_DWORD: @@ -425,7 +323,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming... int64_t fsize = avio_size(pb); if (fsize <= 0 || (int64_t)asf->hdr.file_size <= 0 || - 20*FFABS(fsize - (int64_t)asf->hdr.file_size) < FFMIN(fsize, asf->hdr.file_size)) + FFABS(fsize - (int64_t)asf->hdr.file_size) < FFMIN(fsize, asf->hdr.file_size)/20) st->duration = asf->hdr.play_time / (10000000 / 1000) - start_time; } @@ -480,7 +378,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (is_dvr_ms_audio) { // codec_id and codec_tag are unreliable in dvr_ms // files. Set them later by probing stream. - st->request_probe = 1; + st->internal->request_probe = 1; st->codecpar->codec_tag = 0; } if (st->codecpar->codec_id == AV_CODEC_ID_AAC) @@ -517,6 +415,8 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) tag1 = avio_rl32(pb); avio_skip(pb, 20); if (sizeX > 40) { + if (size < sizeX - 40) + return AVERROR_INVALIDDATA; st->codecpar->extradata_size = ffio_limit(pb, sizeX - 40); st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -608,6 +508,8 @@ static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) ff_get_guid(pb, &g); size = avio_rl16(pb); ext_len = avio_rl32(pb); + if (ext_len < 0) + return AVERROR_INVALIDDATA; avio_skip(pb, ext_len); if (stream_num < 128 && i < FF_ARRAY_ELEMS(asf->streams[stream_num].payload)) { ASFPayload *p = &asf->streams[stream_num].payload[i]; @@ -712,6 +614,9 @@ static int asf_read_metadata(AVFormatContext *s, int64_t size) value_type = avio_rl16(pb); /* value_type */ value_len = avio_rl32(pb); + if (value_len < 0 || value_len > UINT16_MAX) + return AVERROR_INVALIDDATA; + name_len_utf8 = 2*name_len_utf16 + 1; name = av_malloc(name_len_utf8); if (!name) @@ -767,6 +672,8 @@ static int asf_read_marker(AVFormatContext *s, int64_t size) avio_rl32(pb); // send time avio_rl32(pb); // flags name_len = avio_rl32(pb); // name length + if ((unsigned)name_len > INT_MAX / 2) + return AVERROR_INVALIDDATA; if ((ret = avio_get_str16le(pb, name_len * 2, name, sizeof(name))) < name_len) avio_skip(pb, name_len - ret); @@ -846,22 +753,31 @@ static int asf_read_header(AVFormatContext *s) } else { if (!s->keylen) { if (!ff_guidcmp(&g, &ff_asf_content_encryption)) { + AVPacket *pkt = s->internal->parse_pkt; unsigned int len; - AVPacket pkt; av_log(s, AV_LOG_WARNING, "DRM protected stream detected, decoding will likely fail!\n"); len= avio_rl32(pb); av_log(s, AV_LOG_DEBUG, "Secret data:\n"); - if ((ret = av_get_packet(pb, &pkt, len)) < 0) + if ((ret = av_get_packet(pb, pkt, len)) < 0) return ret; - av_hex_dump_log(s, AV_LOG_DEBUG, pkt.data, pkt.size); - av_packet_unref(&pkt); + av_hex_dump_log(s, AV_LOG_DEBUG, pkt->data, pkt->size); + av_packet_unref(pkt); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_Protection_Type", -1, len, 32); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_Key_ID", -1, len, 32); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_License_URL", -1, len, 32); } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) { av_log(s, AV_LOG_WARNING, @@ -1667,11 +1583,11 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, asf->index_read = -1; } - if (asf->index_read > 0 && st->index_entries) { + if (asf->index_read > 0 && st->internal->index_entries) { int index = av_index_search_timestamp(st, pts, flags); if (index >= 0) { /* find the position */ - uint64_t pos = st->index_entries[index].pos; + uint64_t pos = st->internal->index_entries[index].pos; /* do the seek */ av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);