[FFmpeg-devel] [PATCH 01/25] avformat/matroskadec: Fix heap-buffer overflow upon gigantic timestamps
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Sun Aug 29 23:54:52 EEST 2021
Andreas Rheinhardt:
> The WebM DASH Manifest demuxer creates a comma-delimited list of
> all the timestamps of index entries. It allocates 20 bytes per
> timestamp; yet the largest 64bit numbers have 20 decimal digits
> (for int64_t it can be '-'+ 19 digits), so that one needs 21B
> per entry because of the comma (resp. the final NUL).
>
> The code uses snprintf, but snprintf returns the strlen of the string
> that would have been written had the supplied buffer been big enough.
> And if this is 21, then the next entry is written at an offset of 21
> from the current position. So if enough such entries exist, the buffer
> won't suffice.
>
> This commit fixes this by replacing the allocation of buffer for
> the supposedly worst-case with dynamic allocations by using an AVBPrint.
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
> ---
> libavformat/matroskadec.c | 35 +++++++++++++++++++----------------
> 1 file changed, 19 insertions(+), 16 deletions(-)
>
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index 7d79b3d5c4..c67a728737 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -35,6 +35,7 @@
>
> #include "libavutil/avstring.h"
> #include "libavutil/base64.h"
> +#include "libavutil/bprint.h"
> #include "libavutil/dict.h"
> #include "libavutil/intfloat.h"
> #include "libavutil/intreadwrite.h"
> @@ -4146,10 +4147,12 @@ static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range)
> MatroskaDemuxContext *matroska = s->priv_data;
> EbmlList *seekhead_list = &matroska->seekhead;
> MatroskaSeekhead *seekhead = seekhead_list->elem;
> + AVStream *const st = s->streams[0];
> + AVBPrint bprint;
> char *buf;
> int64_t cues_start = -1, cues_end = -1, before_pos, bandwidth;
> int i;
> - int end = 0;
> + int ret;
>
> // determine cues start and end positions
> for (i = 0; i < seekhead_list->nb_elem; i++)
> @@ -4180,6 +4183,9 @@ static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range)
> // parse the cues
> matroska_parse_cues(matroska);
>
> + if (!st->internal->nb_index_entries)
> + return AVERROR_INVALIDDATA;
> +
> // cues start
> av_dict_set_int(&s->streams[0]->metadata, CUES_START, cues_start, 0);
>
> @@ -4199,22 +4205,19 @@ static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range)
> // check if all clusters start with key frames
> av_dict_set_int(&s->streams[0]->metadata, CLUSTER_KEYFRAME, webm_clusters_start_with_keyframe(s), 0);
>
> - // store cue point timestamps as a comma separated list for checking subsegment alignment in
> - // the muxer. assumes that each timestamp cannot be more than 20 characters long.
> - buf = av_malloc_array(s->streams[0]->internal->nb_index_entries, 20);
> - if (!buf) return -1;
> - strcpy(buf, "");
> - for (i = 0; i < s->streams[0]->internal->nb_index_entries; i++) {
> - int ret = snprintf(buf + end, 20,
> - "%" PRId64"%s", s->streams[0]->internal->index_entries[i].timestamp,
> - i != s->streams[0]->internal->nb_index_entries - 1 ? "," : "");
> - if (ret <= 0 || (ret == 20 && i == s->streams[0]->internal->nb_index_entries - 1)) {
> - av_log(s, AV_LOG_ERROR, "timestamp too long.\n");
> - av_free(buf);
> - return AVERROR_INVALIDDATA;
> - }
> - end += ret;
> + // Store cue point timestamps as a comma separated list
> + // for checking subsegment alignment in the muxer.
> + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
> + for (int i = 0; i < st->internal->nb_index_entries; i++)
> + av_bprintf(&bprint, "%" PRId64",", st->internal->index_entries[i].timestamp);
> + if (!av_bprint_is_complete(&bprint)) {
> + av_bprint_finalize(&bprint, NULL);
> + return AVERROR(ENOMEM);
> }
> + // Remove the trailing ','
> + bprint.str[--bprint.len] = '\0';
> + if ((ret = av_bprint_finalize(&bprint, &buf)) < 0)
> + return ret;
> av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS,
> buf, AV_DICT_DONT_STRDUP_VAL);
>
>
Will apply the first three patches of this patchset tomorrow unless
there are objections.
- Andreas
More information about the ffmpeg-devel
mailing list