From b136be8c3c904440b904e9e21db7e4fe70eb46ab Mon Sep 17 00:00:00 2001 From: manuaudio Date: Fri, 14 Aug 2026 22:54:59 -0700 Subject: [PATCH] DSF: do not convert an out of range length to unsigned int DSF::Properties::read computes d->length = d->samplingFrequency > 0 ? static_cast(static_cast(d->sampleCount) * 1000.0 / d->samplingFrequency + 0.5) : 0; sampleCount is a long long taken straight from the file and samplingFrequency is an unsigned int from the file, so the millisecond count can land well outside unsigned int. Converting a floating point value the destination type cannot represent is undefined: taglib/dsf/dsfproperties.cpp:132:35: runtime error: 8.41595e+09 is outside the range of representable values of type 'unsigned int' #0 TagLib::DSF::Properties::read(TagLib::ByteVector const&) #1 TagLib::DSF::Properties::Properties(...) #10 TagLib::FileRef::FileRef(char const*, bool, ...) A negative sampleCount converts just as badly, so guard that too. Report an unknown length instead of converting, matching what a zero sampling frequency already does. Nothing changes for a valid file: tests/data/empty10ms.dsf reads lengthMs=10 bitrate=5645 rate=2822400 ch=2 both before and after. Found by mutating the files in tests/data and running them through a parse, read properties and save round trip under UBSan. Assisted-By: Claude Code (Claude Opus 5) --- taglib/dsf/dsfproperties.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/taglib/dsf/dsfproperties.cpp b/taglib/dsf/dsfproperties.cpp index 0d3ae57f..be7b47df 100644 --- a/taglib/dsf/dsfproperties.cpp +++ b/taglib/dsf/dsfproperties.cpp @@ -26,6 +26,8 @@ #include "dsfproperties.h" +#include + using namespace TagLib; class DSF::Properties::PropertiesPrivate @@ -128,7 +130,16 @@ void DSF::Properties::read(const ByteVector &data) d->bitrate = static_cast( d->samplingFrequency * d->bitsPerSample * d->channelNum / 1000.0 + 0.5); - d->length = d->samplingFrequency > 0 - ? static_cast(static_cast(d->sampleCount) * 1000.0 / d->samplingFrequency + 0.5) - : 0; + + // sampleCount and samplingFrequency both come straight from the file, so the + // millisecond count can land outside unsigned int, and converting a double that + // does not fit the destination type is undefined. Report an unknown length rather + // than converting, which is what a zero sampling frequency already does. + d->length = 0; + if(d->samplingFrequency > 0 && d->sampleCount > 0) { + const double milliseconds = + static_cast(d->sampleCount) * 1000.0 / d->samplingFrequency + 0.5; + if(milliseconds < static_cast(std::numeric_limits::max())) + d->length = static_cast(milliseconds); + } }