X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavformat%2Fmatroskadec.c;h=07f4539723f7ea1fc5117797775c7db7723937a0;hb=a2517fca1e7dc5e0ff63c8490b5c92a9298f5837;hp=16063412de8322a69c5c816a9dbfca4d1741f8ce;hpb=ce838ad950fcf8b2a8823d7606a05077ebe91f9f;p=ffmpeg diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 16063412de8..07f4539723f 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -995,6 +995,15 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, return res; } +static int is_ebml_id_valid(uint32_t id) +{ + // Due to endian nonsense in Matroska, the highest byte with any bits set + // will contain the leading length bit. This bit in turn identifies the + // total byte length of the element by its position within the byte. + unsigned int bits = av_log2(id); + return id && (bits + 7) / 8 == (8 - bits % 8); +} + /* * Allocate and return the entry for the level1 element with the given ID. If * an entry already exists, return the existing entry. @@ -1005,6 +1014,9 @@ static MatroskaLevel1Element *matroska_find_level1_elem(MatroskaDemuxContext *ma int i; MatroskaLevel1Element *elem; + if (!is_ebml_id_valid(id)) + return NULL; + // Some files link to all clusters; useless. if (id == MATROSKA_ID_CLUSTER) return NULL; @@ -1668,6 +1680,14 @@ static int matroska_parse_tracks(AVFormatContext *s) if (!track->codec_id) continue; + if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX || + isnan(track->audio.samplerate)) { + av_log(matroska->ctx, AV_LOG_WARNING, + "Invalid sample rate %f, defaulting to 8000 instead.\n", + track->audio.samplerate); + track->audio.samplerate = 8000; + } + if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { if (!track->default_duration && track->video.frame_rate > 0) track->default_duration = 1000000000 / track->video.frame_rate; @@ -1869,6 +1889,18 @@ static int matroska_parse_tracks(AVFormatContext *s) NULL, NULL, NULL, NULL); avio_write(&b, "TTA1", 4); avio_wl16(&b, 1); + if (track->audio.channels > UINT16_MAX || + track->audio.bitdepth > UINT16_MAX) { + av_log(matroska->ctx, AV_LOG_WARNING, + "Too large audio channel number %"PRIu64 + " or bitdepth %"PRIu64". Skipping track.\n", + track->audio.channels, track->audio.bitdepth); + av_freep(&extradata); + if (matroska->ctx->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + else + continue; + } avio_wl16(&b, track->audio.channels); avio_wl16(&b, track->audio.bitdepth); if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX)