From c0f867bf503e79eba8ee52e1ac53322f88ec2929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Wed, 21 Jun 2023 20:06:09 +0200 Subject: [PATCH] libavformat: fix incorrect handling of incomplete AVBPrint. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change some internal APIs a bit to make it harder to make such mistakes. In particular, have the read chunk functions return an error when the result is incomplete. This might be less flexible, but since there has been no use-case for that so far, avoiding coding mistakes seems better. Add a function to queue a AVBPrint directly (ff_subtitles_queue_insert_bprint). Also fixes a leak in lrcdec when ff_subtitles_queue_insert fails. Signed-off-by: Reimar Döffinger --- libavformat/assdec.c | 4 +++- libavformat/lrcdec.c | 7 ++++++- libavformat/mpsubdec.c | 5 +++-- libavformat/realtextdec.c | 6 +++++- libavformat/samidec.c | 6 +++++- libavformat/srtdec.c | 4 +++- libavformat/subtitles.c | 19 +++++++++++++++---- libavformat/subtitles.h | 14 ++++++++++++-- libavformat/tedcaptionsdec.c | 2 +- libavformat/webvttdec.c | 4 +++- 10 files changed, 56 insertions(+), 15 deletions(-) diff --git a/libavformat/assdec.c b/libavformat/assdec.c index 0915f6fafd..bf7b8a73a2 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -73,6 +73,8 @@ static int read_dialogue(ASSContext *ass, AVBPrint *dst, const uint8_t *p, av_bprint_clear(dst); av_bprintf(dst, "%u,%d,%s", ass->readorder++, layer, p + pos); + if (!av_bprint_is_complete(dst)) + return AVERROR(ENOMEM); /* right strip the buffer */ while (dst->len > 0 && @@ -135,7 +137,7 @@ static int ass_read_header(AVFormatContext *s) av_bprintf(&header, "%s", line.str); continue; } - sub = ff_subtitles_queue_insert(&ass->q, rline.str, rline.len, 0); + sub = ff_subtitles_queue_insert_bprint(&ass->q, &rline, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c index fff39495f8..83bb4a4b75 100644 --- a/libavformat/lrcdec.c +++ b/libavformat/lrcdec.c @@ -171,6 +171,8 @@ static int lrc_read_header(AVFormatContext *s) while(!avio_feof(s->pb)) { int64_t pos = read_line(&line, s->pb); + if (!av_bprint_is_complete(&line)) + goto err_nomem_out; int64_t header_offset = find_header(line.str); if(header_offset >= 0) { char *comma_offset = strchr(line.str, ':'); @@ -205,7 +207,7 @@ static int lrc_read_header(AVFormatContext *s) sub = ff_subtitles_queue_insert(&lrc->q, line.str + ts_strlength, line.len - ts_strlength, 0); if (!sub) - return AVERROR(ENOMEM); + goto err_nomem_out; sub->pos = pos; sub->pts = ts_start - lrc->ts_offset; sub->duration = -1; @@ -216,6 +218,9 @@ static int lrc_read_header(AVFormatContext *s) ff_metadata_conv_ctx(s, NULL, ff_lrc_metadata_conv); av_bprint_finalize(&line, NULL); return 0; +err_nomem_out: + av_bprint_finalize(&line, NULL); + return AVERROR(ENOMEM); } const AVInputFormat ff_lrc_demuxer = { diff --git a/libavformat/mpsubdec.c b/libavformat/mpsubdec.c index d290a41fb9..0374563575 100644 --- a/libavformat/mpsubdec.c +++ b/libavformat/mpsubdec.c @@ -116,9 +116,10 @@ static int mpsub_read_header(AVFormatContext *s) AVPacket *sub; const int64_t pos = avio_tell(s->pb); - ff_subtitles_read_chunk(s->pb, &buf); + res = ff_subtitles_read_chunk(s->pb, &buf); + if (res < 0) goto end; if (buf.len) { - sub = ff_subtitles_queue_insert(&mpsub->q, buf.str, buf.len, 0); + sub = ff_subtitles_queue_insert_bprint(&mpsub->q, &buf, 0); if (!sub) { res = AVERROR(ENOMEM); goto end; diff --git a/libavformat/realtextdec.c b/libavformat/realtextdec.c index c281dec346..7992a5b7fc 100644 --- a/libavformat/realtextdec.c +++ b/libavformat/realtextdec.c @@ -80,6 +80,10 @@ static int realtext_read_header(AVFormatContext *s) const int64_t pos = ff_text_pos(&tr) - (c != 0); int n = ff_smil_extract_next_text_chunk(&tr, &buf, &c); + if (n < 0) { + res = n; + goto end; + } if (n == 0) break; @@ -103,7 +107,7 @@ static int realtext_read_header(AVFormatContext *s) /* if we just read a