Commit 52b653190c for ffmpeg
commit 52b653190c001e132ef35ee6f113b0f413d16e79
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Thu Oct 8 07:31:26 2026 +0200
avformat/nut: Fix files with many streams
The demuxer rejected files with more than 256 streams, it now uses
max_streams as the limit and stores frame code stream ids as int.
The invalid stream ids and the stream limit of the demuxer were found
during triage of the security report.
Fixes: out of array access
Fixes: 0tstIJT8grvU
Fixes: AISLE-2026-0111-00174
Out of array read Replicated through UnModified FFmpeg with ASAN
Fixes: lPmeH2OaqLeE
Invalid frame code stream ids Replicated through UnModified FFmpeg
Fixes: OyhhaqyPDH4L
Unreadable output Replicated through UnModified FFmpeg
Found-by: Joshua Rogers <joshua.rogers@aisle.com>
diff --git a/libavformat/nut.h b/libavformat/nut.h
index a4409ee23d..6d1100d7ea 100644
--- a/libavformat/nut.h
+++ b/libavformat/nut.h
@@ -64,7 +64,7 @@ typedef struct Syncpoint {
typedef struct FrameCode {
uint16_t flags;
- uint8_t stream_id;
+ int stream_id;
uint16_t size_mul;
uint16_t size_lsb;
int16_t pts_delta;
diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c
index b0a997cad6..7ec8526a06 100644
--- a/libavformat/nutdec.c
+++ b/libavformat/nutdec.c
@@ -36,8 +36,6 @@
#include "nut.h"
#include "riff.h"
-#define NUT_MAX_STREAMS 256 /* arbitrary sanity check value */
-
static int64_t nut_read_timestamp(AVFormatContext *s, int stream_index,
int64_t *pos_arg, int64_t pos_limit);
@@ -216,7 +214,7 @@ static int decode_main_header(NUTContext *nut)
if (nut->version > 3)
nut->minor_version = ffio_read_varlen(bc);
- GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS);
+ GET_V(stream_count, tmp > 0 && tmp <= s->max_streams);
nut->max_distance = ffio_read_varlen(bc);
if (nut->max_distance > 65536) {
diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c
index 55efb114c3..a7173b65f9 100644
--- a/libavformat/nutenc.c
+++ b/libavformat/nutenc.c
@@ -188,9 +188,12 @@ static void build_frame_code(AVFormatContext *s)
start++;
}
- for (stream_id = 0; stream_id < s->nb_streams; stream_id++) {
- int start2 = start + (end - start) * stream_id / s->nb_streams;
- int end2 = start + (end - start) * (stream_id + 1) / s->nb_streams;
+ /* Each stream needs up to 6 frame codes, streams beyond use the escape frame codes */
+ int nb_frame_code_streams = FFMIN(s->nb_streams, (end - start) / 6);
+
+ for (stream_id = 0; stream_id < nb_frame_code_streams; stream_id++) {
+ int start2 = start + (end - start) * stream_id / nb_frame_code_streams;
+ int end2 = start + (end - start) * (stream_id + 1) / nb_frame_code_streams;
AVCodecParameters *par = s->streams[stream_id]->codecpar;
int is_audio = par->codec_type == AVMEDIA_TYPE_AUDIO;
int intra_only = /*codec->intra_only || */ is_audio;