From c3d4eef597cc4914ec6177cae83d792158bf8be3 Mon Sep 17 00:00:00 2001 From: manuaudio Date: Sat, 15 Aug 2026 09:00:38 -0700 Subject: [PATCH] Speex: do not convert out of range properties to int Same shape as Vorbis. The length comes from the difference between two 64 bit granule positions over a sample rate read from the Speex header, so a file can declare 2^62 samples at 1 Hz. The millisecond length is then ~4.6e21 and the conversion to int is undefined: taglib/ogg/speex/speexproperties.cpp:165:39: runtime error: 4.61169e+21 is outside the range of representable values of type 'int' The bitrate on the next line is reachable the other way round, with one sample at a high declared rate making the divisor tiny: taglib/ogg/speex/speexproperties.cpp:166:39: runtime error: 3.61877e+13 is outside the range of representable values of type 'int' Leave the field at its default rather than converting. Two reports before the change, none after. The 23 FLAC, APE, Ogg Vorbis, Opus and Speex files in tests/data report identical channels, sample rate, bitrate and length before and after, and the suite runs 576 tests either way. Assisted-By: Claude Code (Claude Opus 5) --- taglib/ogg/speex/speexproperties.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/taglib/ogg/speex/speexproperties.cpp b/taglib/ogg/speex/speexproperties.cpp index 3f9bf5bb..30aeb59f 100644 --- a/taglib/ogg/speex/speexproperties.cpp +++ b/taglib/ogg/speex/speexproperties.cpp @@ -29,6 +29,8 @@ #include "speexproperties.h" +#include + #include "tstring.h" #include "tdebug.h" #include "oggpageheader.h" @@ -162,8 +164,18 @@ void Speex::Properties::read(File *file) for (unsigned int i = 0; i < 2; ++i) { fileLengthWithoutOverhead -= file->packet(i).size(); } - d->length = static_cast(length + 0.5); - d->bitrate = static_cast(static_cast(fileLengthWithoutOverhead) * 8.0 / length + 0.5); + // The granule positions are 64 bit and the sample rate is read from the + // file, so the millisecond length can land outside int, and a short + // stream at a high rate does the same to the bitrate. Converting a + // double the destination type cannot represent is undefined, so leave + // the field at its default instead. + if(length > 0.0 && length < static_cast(std::numeric_limits::max())) { + d->length = static_cast(length + 0.5); + + const double bitrate = static_cast(fileLengthWithoutOverhead) * 8.0 / length; + if(bitrate >= 0.0 && bitrate < static_cast(std::numeric_limits::max())) + d->bitrate = static_cast(bitrate + 0.5); + } } } else {