PR #22638 opened by sanks011 URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22638 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22638.patch
Multiple demuxers call avio_read() without checking its return value. When input is truncated, destination buffers remain uninitialized but are still used for offset calculations, memcmp, and metadata handling. This results in undefined behavior (detectable with Valgrind/MSan). Fix this by checking the return value of avio_read() in: - dss.c: dss_read_seek() - check before using header buffer - dtshddec.c: FILEINFO chunk - check before using value buffer - mlvdec.c: check_file_header() - check before memcmp on version Fixes: #21520 From ee0b1c0b0981ed7965816597b531fee87a95a5ee Mon Sep 17 00:00:00 2001 From: Sankalpa Sarkar <[email protected]> Date: Fri, 27 Mar 2026 21:12:46 +0530 Subject: [PATCH] avformat: check avio_read() return values in dss/dtshd/mlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple demuxers call avio_read() without checking its return value. When input is truncated, destination buffers remain uninitialized but are still used for offset calculations, memcmp, and metadata handling. This results in undefined behavior (detectable with Valgrind/MSan). Fix this by checking the return value of avio_read() in: - dss.c: dss_read_seek() — check before using header buffer - dtshddec.c: FILEINFO chunk — check before using value buffer - mlvdec.c: check_file_header() — check before memcmp on version Fixes: #21520 --- libavformat/dss.c | 4 +++- libavformat/dtshddec.c | 6 +++++- libavformat/mlvdec.c | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libavformat/dss.c b/libavformat/dss.c index 6cabdb5421..aa7ef08622 100644 --- a/libavformat/dss.c +++ b/libavformat/dss.c @@ -339,7 +339,9 @@ static int dss_read_seek(AVFormatContext *s, int stream_index, if (ret < 0) return ret; - avio_read(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); + ret = avio_read(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); + if (ret < DSS_AUDIO_BLOCK_HEADER_SIZE) + return ret < 0 ? ret : AVERROR_INVALIDDATA; ctx->swap = !!(header[0] & 0x80); offset = 2*header[1] + 2*ctx->swap; if (offset < DSS_AUDIO_BLOCK_HEADER_SIZE) diff --git a/libavformat/dtshddec.c b/libavformat/dtshddec.c index b980fde6a9..e516eba2f1 100644 --- a/libavformat/dtshddec.c +++ b/libavformat/dtshddec.c @@ -125,7 +125,11 @@ static int dtshd_read_header(AVFormatContext *s) value = av_malloc(chunk_size); if (!value) goto skip; - avio_read(pb, value, chunk_size); + ret = avio_read(pb, value, chunk_size); + if (ret < chunk_size) { + av_free(value); + goto skip; + } value[chunk_size - 1] = 0; av_dict_set(&s->metadata, "fileinfo", value, AV_DICT_DONT_STRDUP_VAL); diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c index fa35bc9c45..d9d7815f54 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -79,7 +79,8 @@ static int check_file_header(AVIOContext *pb, uint64_t guid) size = avio_rl32(pb); if (size < 52) return AVERROR_INVALIDDATA; - avio_read(pb, version, 8); + if (avio_read(pb, version, 8) < 8) + return AVERROR_INVALIDDATA; if (memcmp(version, MLV_VERSION, 5) || avio_rl64(pb) != guid) return AVERROR_INVALIDDATA; avio_skip(pb, size - 24); -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
