| Index: patched-ffmpeg-mt/libavformat/mov.c
|
| ===================================================================
|
| --- patched-ffmpeg-mt/libavformat/mov.c (revision 41250)
|
| +++ patched-ffmpeg-mt/libavformat/mov.c (working copy)
|
| @@ -93,6 +93,43 @@
|
| return 0;
|
| }
|
|
|
| +static const uint32_t mac_to_unicode[128] = {
|
| + 0x00C4,0x00C5,0x00C7,0x00C9,0x00D1,0x00D6,0x00DC,0x00E1,
|
| + 0x00E0,0x00E2,0x00E4,0x00E3,0x00E5,0x00E7,0x00E9,0x00E8,
|
| + 0x00EA,0x00EB,0x00ED,0x00EC,0x00EE,0x00EF,0x00F1,0x00F3,
|
| + 0x00F2,0x00F4,0x00F6,0x00F5,0x00FA,0x00F9,0x00FB,0x00FC,
|
| + 0x2020,0x00B0,0x00A2,0x00A3,0x00A7,0x2022,0x00B6,0x00DF,
|
| + 0x00AE,0x00A9,0x2122,0x00B4,0x00A8,0x2260,0x00C6,0x00D8,
|
| + 0x221E,0x00B1,0x2264,0x2265,0x00A5,0x00B5,0x2202,0x2211,
|
| + 0x220F,0x03C0,0x222B,0x00AA,0x00BA,0x03A9,0x00E6,0x00F8,
|
| + 0x00BF,0x00A1,0x00AC,0x221A,0x0192,0x2248,0x2206,0x00AB,
|
| + 0x00BB,0x2026,0x00A0,0x00C0,0x00C3,0x00D5,0x0152,0x0153,
|
| + 0x2013,0x2014,0x201C,0x201D,0x2018,0x2019,0x00F7,0x25CA,
|
| + 0x00FF,0x0178,0x2044,0x20AC,0x2039,0x203A,0xFB01,0xFB02,
|
| + 0x2021,0x00B7,0x201A,0x201E,0x2030,0x00C2,0x00CA,0x00C1,
|
| + 0x00CB,0x00C8,0x00CD,0x00CE,0x00CF,0x00CC,0x00D3,0x00D4,
|
| + 0xF8FF,0x00D2,0x00DA,0x00DB,0x00D9,0x0131,0x02C6,0x02DC,
|
| + 0x00AF,0x02D8,0x02D9,0x02DA,0x00B8,0x02DD,0x02DB,0x02C7,
|
| +};
|
| +
|
| +static int mov_read_mac_string(MOVContext *c, ByteIOContext *pb, int len,
|
| + char *dst, int dstlen)
|
| +{
|
| + char *p = dst;
|
| + char *end = dst+dstlen-1;
|
| + int i;
|
| +
|
| + for (i = 0; i < len; i++) {
|
| + uint8_t t, c = get_byte(pb);
|
| + if (c < 0x80 && p < end)
|
| + *p++ = c;
|
| + else
|
| + PUT_UTF8(mac_to_unicode[c-0x80], t, if (p < end) *p++ = t;);
|
| + }
|
| + *p = 0;
|
| + return p - dst;
|
| +}
|
| +
|
| static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
| {
|
| #ifdef MOV_EXPORT_ALL_METADATA
|
| @@ -100,7 +137,8 @@
|
| #endif
|
| char str[1024], key2[16], language[4] = {0};
|
| const char *key = NULL;
|
| - uint16_t str_size;
|
| + uint16_t str_size, langcode = 0;
|
| + uint32_t data_type = 0;
|
| int (*parse)(MOVContext*, ByteIOContext*, unsigned) = NULL;
|
|
|
| switch (atom.type) {
|
| @@ -130,14 +168,15 @@
|
| int data_size = get_be32(pb);
|
| int tag = get_le32(pb);
|
| if (tag == MKTAG('d','a','t','a')) {
|
| - get_be32(pb); // type
|
| + data_type = get_be32(pb); // type
|
| get_be32(pb); // unknown
|
| str_size = data_size - 16;
|
| atom.size -= 16;
|
| } else return 0;
|
| } else if (atom.size > 4 && key && !c->itunes_metadata) {
|
| str_size = get_be16(pb); // string length
|
| - ff_mov_lang_to_iso639(get_be16(pb), language);
|
| + langcode = get_be16(pb);
|
| + ff_mov_lang_to_iso639(langcode, language);
|
| atom.size -= 4;
|
| } else
|
| str_size = atom.size;
|
| @@ -159,8 +198,12 @@
|
| if (parse)
|
| parse(c, pb, str_size);
|
| else {
|
| - get_buffer(pb, str, str_size);
|
| - str[str_size] = 0;
|
| + if (data_type == 3 || (data_type == 0 && langcode < 0x800)) { // MAC Encoded
|
| + mov_read_mac_string(c, pb, str_size, str, sizeof(str));
|
| + } else {
|
| + get_buffer(pb, str, str_size);
|
| + str[str_size] = 0;
|
| + }
|
| av_metadata_set(&c->fc->metadata, key, str);
|
| if (*language && strcmp(language, "und")) {
|
| snprintf(key2, sizeof(key2), "%s-%s", key, language);
|
| @@ -398,7 +441,7 @@
|
| return len;
|
| }
|
|
|
| -int mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag)
|
| +static int mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag)
|
| {
|
| int len;
|
| *tag = get_byte(pb);
|
| @@ -913,8 +956,7 @@
|
| (format >> 24) & 0xff, st->codec->codec_type);
|
|
|
| if(st->codec->codec_type==CODEC_TYPE_VIDEO) {
|
| - uint8_t codec_name[32];
|
| - unsigned int color_depth;
|
| + unsigned int color_depth, len;
|
| int color_greyscale;
|
|
|
| st->codec->codec_id = id;
|
| @@ -932,19 +974,15 @@
|
| get_be32(pb); /* data size, always 0 */
|
| get_be16(pb); /* frames per samples */
|
|
|
| - get_buffer(pb, codec_name, 32); /* codec name, pascal string */
|
| - if (codec_name[0] <= 31) {
|
| - int i;
|
| - int pos = 0;
|
| - for (i = 0; i < codec_name[0] && pos < sizeof(st->codec->codec_name) - 3; i++) {
|
| - uint8_t tmp;
|
| - PUT_UTF8(codec_name[i+1], tmp, st->codec->codec_name[pos++] = tmp;)
|
| - }
|
| - st->codec->codec_name[pos] = 0;
|
| - /* codec_tag YV12 triggers an UV swap in rawdec.c */
|
| - if (!memcmp(st->codec->codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25))
|
| - st->codec->codec_tag=MKTAG('I', '4', '2', '0');
|
| - }
|
| + len = get_byte(pb); /* codec name, pascal string */
|
| + if (len > 31)
|
| + len = 31;
|
| + mov_read_mac_string(c, pb, len, st->codec->codec_name, 32);
|
| + if (len < 31)
|
| + url_fskip(pb, 31 - len);
|
| + /* codec_tag YV12 triggers an UV swap in rawdec.c */
|
| + if (!memcmp(st->codec->codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25))
|
| + st->codec->codec_tag=MKTAG('I', '4', '2', '0');
|
|
|
| st->codec->bits_per_coded_sample = get_be16(pb); /* depth */
|
| st->codec->color_table_id = get_be16(pb); /* colortable id */
|
| @@ -1464,6 +1502,13 @@
|
|
|
| current_dts -= sc->dts_shift;
|
|
|
| + if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries))
|
| + return;
|
| + st->index_entries = av_malloc(sc->sample_count*sizeof(*st->index_entries));
|
| + if (!st->index_entries)
|
| + return;
|
| + st->index_entries_allocated_size = sc->sample_count*sizeof(*st->index_entries);
|
| +
|
| for (i = 0; i < sc->chunk_count; i++) {
|
| current_offset = sc->chunk_offsets[i];
|
| if (stsc_index + 1 < sc->stsc_count &&
|
| @@ -1490,8 +1535,12 @@
|
| sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
|
| if(sc->pseudo_stream_id == -1 ||
|
| sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
|
| - av_add_index_entry(st, current_offset, current_dts, sample_size, distance,
|
| - keyframe ? AVINDEX_KEYFRAME : 0);
|
| + AVIndexEntry *e = &st->index_entries[st->nb_index_entries++];
|
| + e->pos = current_offset;
|
| + e->timestamp = current_dts;
|
| + e->size = sample_size;
|
| + e->min_distance = distance;
|
| + e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
|
| dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
|
| "size %d, distance %d, keyframe %d\n", st->index, current_sample,
|
| current_offset, current_dts, sample_size, distance, keyframe);
|
| @@ -1512,21 +1561,52 @@
|
| if (st->duration > 0)
|
| st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration;
|
| } else {
|
| + unsigned chunk_samples, total = 0;
|
| +
|
| + // compute total chunk count
|
| + for (i = 0; i < sc->stsc_count; i++) {
|
| + unsigned count, chunk_count;
|
| +
|
| + chunk_samples = sc->stsc_data[i].count;
|
| + if (sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
|
| + av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
|
| + return;
|
| + }
|
| +
|
| + if (sc->samples_per_frame >= 160) { // gsm
|
| + count = chunk_samples / sc->samples_per_frame;
|
| + } else if (sc->samples_per_frame > 1) {
|
| + unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
|
| + count = (chunk_samples+samples-1) / samples;
|
| + } else {
|
| + count = (chunk_samples+1023) / 1024;
|
| + }
|
| +
|
| + if (i < sc->stsc_count - 1)
|
| + chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
|
| + else
|
| + chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
|
| + total += chunk_count * count;
|
| + }
|
| +
|
| + dprintf(mov->fc, "chunk count %d\n", total);
|
| + if (total >= UINT_MAX / sizeof(*st->index_entries))
|
| + return;
|
| + st->index_entries = av_malloc(total*sizeof(*st->index_entries));
|
| + if (!st->index_entries)
|
| + return;
|
| + st->index_entries_allocated_size = total*sizeof(*st->index_entries);
|
| +
|
| + // populate index
|
| for (i = 0; i < sc->chunk_count; i++) {
|
| - unsigned chunk_samples;
|
| -
|
| current_offset = sc->chunk_offsets[i];
|
| if (stsc_index + 1 < sc->stsc_count &&
|
| i + 1 == sc->stsc_data[stsc_index + 1].first)
|
| stsc_index++;
|
| chunk_samples = sc->stsc_data[stsc_index].count;
|
|
|
| - if (sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
|
| - av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
|
| - return;
|
| - }
|
| -
|
| while (chunk_samples > 0) {
|
| + AVIndexEntry *e;
|
| unsigned size, samples;
|
|
|
| if (sc->samples_per_frame >= 160) { // gsm
|
| @@ -1543,7 +1623,16 @@
|
| }
|
| }
|
|
|
| - av_add_index_entry(st, current_offset, current_dts, size, 0, AVINDEX_KEYFRAME);
|
| + if (st->nb_index_entries >= total) {
|
| + av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %d\n", total);
|
| + return;
|
| + }
|
| + e = &st->index_entries[st->nb_index_entries++];
|
| + e->pos = current_offset;
|
| + e->timestamp = current_dts;
|
| + e->size = size;
|
| + e->min_distance = 0;
|
| + e->flags = AVINDEX_KEYFRAME;
|
| dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", "
|
| "size %d, duration %d\n", st->index, i, current_offset, current_dts,
|
| size, samples);
|
| @@ -1558,11 +1647,8 @@
|
|
|
| static int mov_open_dref(ByteIOContext **pb, char *src, MOVDref *ref)
|
| {
|
| - /* try absolute path */
|
| - if (!url_fopen(pb, ref->path, URL_RDONLY))
|
| - return 0;
|
| -
|
| - /* try relative path */
|
| + /* try relative path, we do not try the absolute because it can leak information about our
|
| + system to an attacker */
|
| if (ref->nlvl_to > 0 && ref->nlvl_from > 0) {
|
| char filename[1024];
|
| char *src_path;
|
| @@ -1585,7 +1671,7 @@
|
| }
|
|
|
| /* compose filename if next level down to target was found */
|
| - if (i == ref->nlvl_to - 1) {
|
| + if (i == ref->nlvl_to - 1 && src_path - src < sizeof(filename)) {
|
| memcpy(filename, src, src_path - src);
|
| filename[src_path - src] = 0;
|
|
|
|
|