avformat: check avio_read() return values in dss/dtshd/mlv

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
This commit is contained in:
Sankalpa Sarkar
2026-03-27 21:12:46 +05:30
committed by Marton Balint
parent 1e031d4af7
commit 65eed0732c
3 changed files with 15 additions and 3 deletions

View File

@@ -26,6 +26,7 @@
#include "avformat.h"
#include "demux.h"
#include "internal.h"
#include "avio_internal.h"
#define DSS_HEAD_OFFSET_AUTHOR 0xc
#define DSS_AUTHOR_SIZE 16
@@ -339,7 +340,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)

View File

@@ -26,6 +26,7 @@
#include "avformat.h"
#include "demux.h"
#include "internal.h"
#include "avio_internal.h"
#define AUPR_HDR 0x415550522D484452
#define AUPRINFO 0x41555052494E464F
@@ -125,7 +126,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);

View File

@@ -36,6 +36,7 @@
#include "avformat.h"
#include "demux.h"
#include "internal.h"
#include "avio_internal.h"
#include "riff.h"
#define MLV_VERSION "v2.0"
@@ -74,12 +75,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);