From be16cb1f801586111bfb2fbeeb2e5382a851da4d Mon Sep 17 00:00:00 2001 From: Sankalpa Sarkar 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 (cherry picked from commit 65eed0732cadc42b3689788f175d921974f9c074) Signed-off-by: Michael Niedermayer --- libavformat/dss.c | 5 ++++- libavformat/dtshddec.c | 7 ++++++- libavformat/mlvdec.c | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libavformat/dss.c b/libavformat/dss.c index d619ea00d7..0367060d83 100644 --- a/libavformat/dss.c +++ b/libavformat/dss.c @@ -24,6 +24,7 @@ #include "avformat.h" #include "internal.h" +#include "avio_internal.h" #define DSS_HEAD_OFFSET_AUTHOR 0xc #define DSS_AUTHOR_SIZE 16 @@ -336,7 +337,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 = ffio_read_size(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); + if (ret < 0) + return ret; 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 a3dea0668f..cbc17bf7fd 100644 --- a/libavformat/dtshddec.c +++ b/libavformat/dtshddec.c @@ -24,6 +24,7 @@ #include "libavcodec/dca.h" #include "avformat.h" #include "internal.h" +#include "avio_internal.h" #define AUPR_HDR 0x415550522D484452 #define AUPRINFO 0x41555052494E464F @@ -117,7 +118,11 @@ static int dtshd_read_header(AVFormatContext *s) value = av_malloc(chunk_size); if (!value) goto skip; - avio_read(pb, value, chunk_size); + ret = ffio_read_size(pb, value, chunk_size); + if (ret < 0) { + 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 026d2332b5..cff47988e5 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -32,6 +32,7 @@ #include "avformat.h" #include "demux.h" #include "internal.h" +#include "avio_internal.h" #include "riff.h" #define MLV_VERSION "v2.0" @@ -66,12 +67,15 @@ static int check_file_header(AVIOContext *pb, uint64_t guid) { unsigned int size; uint8_t version[8]; + int ret; avio_skip(pb, 4); size = avio_rl32(pb); if (size < 52) return AVERROR_INVALIDDATA; - avio_read(pb, version, 8); + ret = ffio_read_size(pb, version, 8); + if (ret < 0) + return ret; if (memcmp(version, MLV_VERSION, 5) || avio_rl64(pb) != guid) return AVERROR_INVALIDDATA; avio_skip(pb, size - 24);