FLAC: do not convert out of range properties to int

STREAMINFO carries the total sample count in a 36 bit field and the
sample rate in a 20 bit one, so a structurally valid file can declare
2^36-1 frames at 1 Hz. The millisecond length is then ~6.9e13 and the
conversion to int is undefined:

  taglib/flac/flacproperties.cpp:136:35: runtime error: 6.87195e+13 is
  outside the range of representable values of type 'int'

The bitrate on the next line is reachable the other way round, with a
short stream at a high declared rate making the divisor tiny:

  taglib/flac/flacproperties.cpp:137:35: runtime error: 1.75922e+10 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)
This commit is contained in:
manuaudio
2026-08-15 18:18:23 +02:00
committed by Urs Fleisch
parent df6c8e15d1
commit 4c3e3cf1b8
+13 -2
View File
@@ -25,6 +25,8 @@
#include "flacproperties.h"
#include <limits>
#include "tstring.h"
#include "tdebug.h"
@@ -131,10 +133,19 @@ void FLAC::Properties::read(const ByteVector &data, offset_t streamLength)
d->sampleFrames = (hi << 32) | lo;
// The frame count is a 36 bit field and the sample rate a 20 bit one, 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(d->sampleFrames > 0 && d->sampleRate > 0) {
const auto length = static_cast<double>(d->sampleFrames) * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(static_cast<double>(streamLength) * 8.0 / length + 0.5);
if(length > 0.0 && length < static_cast<double>(std::numeric_limits<int>::max())) {
d->length = static_cast<int>(length + 0.5);
const double bitrate = static_cast<double>(streamLength) * 8.0 / length;
if(bitrate >= 0.0 && bitrate < static_cast<double>(std::numeric_limits<int>::max()))
d->bitrate = static_cast<int>(bitrate + 0.5);
}
}
if(data.size() >= pos + 16)