1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

avformat/mov: Check sample_rate in stsd version 2 audio

The QuickTime SoundDescription version 2 layout stores the sample rate as
a 64 bit float. Converting it to int is undefined behaviour when the value
does not fit into int, NaN included -- and NaN slips through every
integer-style range check because all comparisons against it are false.

The sample_rate < 0 check in ff_mov_read_stsd_entries() runs after the
conversion has already happened, so it cannot prevent this.

Validate the double before converting it, matching soxdec.

Zero is deliberately still accepted: mov_finalize_stsd_codec() substitutes
sc->time_scale for a zero audio sample rate, and rejecting zero here would
remove that existing recovery without being needed for the conversion fix.
Negative, NaN, infinite and out-of-range values are rejected before the
conversion.

Fixes: mov.c:3031 runtime error: nan is outside the range of
       representable values of type 'int'

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Furkan Efe Can <caglarf646@gmail.com>
This commit is contained in:
Furkan Efe Can
2026-10-13 00:39:45 +03:00
committed by michaelni
parent a7b20ee103
commit 3be6c2d943

View File

@@ -2995,8 +2995,8 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
}
}
static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
AVStream *st, MOVStreamContext *sc)
static int mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
AVStream *st, MOVStreamContext *sc)
{
int bits_per_sample, flags;
uint16_t version = avio_rb16(pb);
@@ -3035,8 +3035,18 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
sc->bytes_per_frame = avio_rb32(pb);
avio_rb32(pb); /* bytes per sample */
} else if (version == 2) {
double sample_rate;
avio_rb32(pb); /* sizeof struct only */
st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
sample_rate = av_int2double(avio_rb64(pb));
if (sample_rate < 0 || sample_rate > INT_MAX ||
isnan(sample_rate)) {
av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %g\n",
sample_rate);
return AVERROR_INVALIDDATA;
}
st->codecpar->sample_rate = sample_rate;
channel_count = avio_rb32(pb);
st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
st->codecpar->ch_layout.nb_channels = channel_count;
@@ -3114,6 +3124,8 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
st->codecpar->bits_per_coded_sample = bits_per_sample;
sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
}
return 0;
}
static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
@@ -3407,7 +3419,9 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
mov_parse_stsd_video(c, pb, st, sc);
} else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
mov_parse_stsd_audio(c, pb, st, sc);
ret = mov_parse_stsd_audio(c, pb, st, sc);
if (ret < 0)
return ret;
if (st->codecpar->sample_rate < 0) {
av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate);
return AVERROR_INVALIDDATA;