Commit 32d6bf11a7 for ffmpeg
commit 32d6bf11a76e91fa64e8fef7ecd828a57eb31c66
Author: Kacper Michajłow <kasper93@gmail.com>
Date: Tue Sep 29 11:34:11 2026 +0200
avformat/hls: fix subtitle playlist IO buffer leaks
The IO context of a playlist owns its buffer. Allocate only the buffer it
is initialized with, and free the previous one when init_subtitle_context()
sets it up again.
Fixes: 540482604/clusterfuzz-testcase-minimized-ffmpeg_dem_HLS_fuzzer-6393605404295168
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
diff --git a/libavformat/hls.c b/libavformat/hls.c
index daca226f67..93ef1bd0c0 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -102,7 +102,6 @@ enum PlaylistType {
struct playlist {
char url[MAX_URL_SIZE];
FFIOContext pb;
- uint8_t* read_buffer;
AVIOContext *input;
int input_read_done;
int input_reuse;
@@ -1929,19 +1928,21 @@ static int init_subtitle_context(struct playlist *pls)
HLSContext *c = pls->parent->priv_data;
const AVInputFormat *in_fmt;
AVDictionary *opts = NULL;
+ uint8_t *buf;
int ret;
if (!(pls->ctx = avformat_alloc_context()))
return AVERROR(ENOMEM);
- pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
- if (!pls->read_buffer) {
+ buf = av_malloc(INITIAL_BUFFER_SIZE);
+ if (!buf) {
avformat_free_context(pls->ctx);
pls->ctx = NULL;
return AVERROR(ENOMEM);
}
- ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls,
+ av_freep(&pls->pb.pub.buffer);
+ ffio_init_context(&pls->pb, buf, INITIAL_BUFFER_SIZE, 0, pls,
read_data_subtitle_segment, NULL, NULL);
pls->pb.pub.seekable = 0;
pls->ctx->pb = &pls->pb.pub;
@@ -2412,6 +2413,8 @@ static int hls_read_header(AVFormatContext *s)
char *url;
AVDictionary *options = NULL;
struct segment *seg = NULL;
+ uint8_t *buf;
+ int buf_size;
if (!(pls->ctx = avformat_alloc_context()))
return AVERROR(ENOMEM);
@@ -2435,19 +2438,21 @@ static int hls_read_header(AVFormatContext *s)
pls->cur_seq_no = highest_cur_seq_no;
}
- pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
- if (!pls->read_buffer){
+ if (pls->is_subtitle) {
+ buf_size = strlen("WEBVTT\n");
+ buf = av_memdup("WEBVTT\n", buf_size);
+ } else {
+ buf_size = INITIAL_BUFFER_SIZE;
+ buf = av_malloc(buf_size);
+ }
+ if (!buf) {
avformat_free_context(pls->ctx);
pls->ctx = NULL;
return AVERROR(ENOMEM);
}
- if (pls->is_subtitle)
- ffio_init_context(&pls->pb, (unsigned char*)av_strdup("WEBVTT\n"), (int)strlen("WEBVTT\n"), 0, pls,
- NULL, NULL, NULL);
- else
- ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls,
- read_data_continuous, NULL, NULL);
+ ffio_init_context(&pls->pb, buf, buf_size, 0, pls,
+ pls->is_subtitle ? NULL : read_data_continuous, NULL, NULL);
/*
* If encryption scheme is SAMPLE-AES, try to read ID3 tags of