Commit da7e06f4be for ffmpeg
commit da7e06f4be321723d6bbe1e6f9e1879f814bbfb5
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Wed Nov 11 15:24:54 2026 +0100
avcodec/microdvddec: do not read the tags beyond the packet
The tag parser expects a 0 terminated string. ff_decode_subtitle_text()
provides one, which makes the checks against the packet end redundant.
Fixes: out of array read
Fixes: AiKrgI6Y6Kco
Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25134
Out of array read Replicated through API with ASAN
Read beyond the packet Replicated through UnModified FFmpeg with the ass output
diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c
index 4065fd0257..95f0166bf4 100644
--- a/libavcodec/microdvddec.c
+++ b/libavcodec/microdvddec.c
@@ -33,6 +33,7 @@
#include "avcodec.h"
#include "ass.h"
#include "codec_internal.h"
+#include "decode.h"
static int indexof(const char *s, int c)
{
@@ -283,31 +284,32 @@ static int microdvd_decode_frame(AVCodecContext *avctx, AVSubtitle *sub,
int *got_sub_ptr, const AVPacket *avpkt)
{
AVBPrint new_line;
- char *line = avpkt->data;
- char *end = avpkt->data + avpkt->size;
+ char *line = (char *)ff_decode_subtitle_text(avctx, avpkt);
FFASSDecoderContext *s = avctx->priv_data;
struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}};
if (avpkt->size <= 0)
return avpkt->size;
+ if (!line)
+ return AVERROR(ENOMEM);
av_bprint_init(&new_line, 0, 2048);
// subtitle content
- while (line < end && *line) {
+ while (*line) {
// parse MicroDVD tags, and open them in ASS
line = microdvd_load_tags(tags, line);
microdvd_open_tags(&new_line, tags);
// simple copy until EOL or forced carriage return
- while (line < end && *line && *line != '|') {
+ while (*line && *line != '|') {
av_bprint_chars(&new_line, *line, 1);
line++;
}
// line split
- if (line < end && *line == '|') {
+ if (*line == '|') {
microdvd_close_no_persistent_tags(&new_line, tags);
av_bprintf(&new_line, "\\N");
line++;