From a64e7543f85f5a3a557023ee838ec5921d36159b Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Mon, 20 Apr 2026 15:08:37 +0200 Subject: [PATCH] Fix DSD/DSF signed integer issues (#1332) --- taglib/dsdiff/dsdifffile.cpp | 54 ++++++++++++++++++------------------ taglib/dsf/dsffile.cpp | 30 ++++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/taglib/dsdiff/dsdifffile.cpp b/taglib/dsdiff/dsdifffile.cpp index 22cd3642..90d1315b 100644 --- a/taglib/dsdiff/dsdifffile.cpp +++ b/taglib/dsdiff/dsdifffile.cpp @@ -312,7 +312,7 @@ void DSDIFF::File::removeRootChunk(unsigned int i) unsigned long long chunkSize = d->chunks[i].size + d->chunks[i].padding + 12; d->size -= chunkSize; - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); removeBlock(d->chunks[i].offset - 12, chunkSize); @@ -346,7 +346,7 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data) // First we update the global size d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding); - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); // Now update the specific chunk @@ -383,7 +383,7 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da // First we update the global size d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12; - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); // Now add the chunk to the file const unsigned long long fileLength = length(); @@ -410,12 +410,12 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum) unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12; d->size -= removedChunkTotalSize; - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); // Update child chunk size d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize; - insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, + insert(ByteVector::fromULongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, d->endianness == BigEndian), d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8); // Remove the chunk @@ -462,13 +462,13 @@ void DSDIFF::File::setChildChunkData(unsigned int i, d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding); - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); // And the PROP chunk size d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding); - insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, + insert(ByteVector::fromULongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, d->endianness == BigEndian), d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8); @@ -538,13 +538,13 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name, // First we update the global size d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12; - insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8); + insert(ByteVector::fromULongLong(d->size, d->endianness == BigEndian), 4, 8); // And the child chunk size d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1) + ((data.size() + 1) & ~1) + 12; - insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, + insert(ByteVector::fromULongLong(d->chunks[d->childChunkIndex[childChunkNum]].size, d->endianness == BigEndian), d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8); @@ -606,14 +606,14 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty bool bigEndian = d->endianness == BigEndian; d->type = readBlock(4); - d->size = readBlock(8).toLongLong(bigEndian); + d->size = readBlock(8).toULongLong(bigEndian); d->format = readBlock(4); // + 12: chunk header at least, fix for additional junk bytes while(tell() + 12 <= length()) { ByteVector chunkName = readBlock(4); - unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian); + unsigned long long chunkSize = readBlock(8).toULongLong(bigEndian); if(!isValidChunkID(chunkName)) { debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID"); @@ -666,14 +666,14 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty } else if(d->chunks[i].name == "DST ") { // Now decode the chunks inside the DST chunk to read the DST Frame Information one - long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size; + unsigned long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size; seek(d->chunks[i].offset); audioDataSizeinBytes = d->chunks[i].size; - while(tell() + 12 <= dstChunkEnd) { + while(static_cast(tell()) + 12 <= dstChunkEnd) { ByteVector dstChunkName = readBlock(4); - long long dstChunkSize = readBlock(8).toLongLong(bigEndian); + unsigned long long dstChunkSize = readBlock(8).toULongLong(bigEndian); if(!isValidChunkID(dstChunkName)) { debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID"); @@ -681,7 +681,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty break; } - if(static_cast(tell()) + dstChunkSize > dstChunkEnd) { + if(tell() + dstChunkSize > dstChunkEnd) { debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid size (larger than the DST chunk)"); setValid(false); @@ -708,14 +708,14 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty } } else if(d->chunks[i].name == "PROP") { - d->childChunkIndex[PROPChunk] = i; + d->childChunkIndex[PROPChunk] = static_cast(i); // Now decodes the chunks inside the PROP chunk - long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size; + unsigned long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size; // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk seek(d->chunks[i].offset + 4); - while(tell() + 12 <= propChunkEnd) { + while(static_cast(tell()) + 12 <= propChunkEnd) { ByteVector propChunkName = readBlock(4); - long long propChunkSize = readBlock(8).toLongLong(bigEndian); + unsigned long long propChunkSize = readBlock(8).toULongLong(bigEndian); if(!isValidChunkID(propChunkName)) { debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID"); @@ -723,7 +723,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty break; } - if(static_cast(tell()) + propChunkSize > propChunkEnd) { + if(tell() + propChunkSize > propChunkEnd) { debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid size (larger than the PROP chunk)"); setValid(false); @@ -751,17 +751,17 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty } } else if(d->chunks[i].name == "DIIN") { - d->childChunkIndex[DIINChunk] = i; + d->childChunkIndex[DIINChunk] = static_cast(i); d->hasDiin = true; // Now decode the chunks inside the DIIN chunk - long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size; + unsigned long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size; seek(d->chunks[i].offset); - while(tell() + 12 <= diinChunkEnd) { + while(static_cast(tell()) + 12 <= diinChunkEnd) { ByteVector diinChunkName = readBlock(4); - long long diinChunkSize = readBlock(8).toLongLong(bigEndian); + unsigned long long diinChunkSize = readBlock(8).toULongLong(bigEndian); if(!isValidChunkID(diinChunkName)) { debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID"); @@ -769,7 +769,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty break; } - if(static_cast(tell()) + diinChunkSize > diinChunkEnd) { + if(tell() + diinChunkSize > diinChunkEnd) { debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid size (larger than the DIIN chunk)"); setValid(false); @@ -825,7 +825,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty if(d->childChunks[PROPChunk][i].name == "ID3 " || d->childChunks[PROPChunk][i].name == "id3 ") { if(d->hasID3v2) { - d->duplicateID3V2chunkIndex = i; + d->duplicateID3V2chunkIndex = static_cast(i); // ID3V2 tag has already been found at root level continue; } @@ -913,7 +913,7 @@ void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, combined.append(ByteVector(leadingPadding, '\x00')); combined.append(name); - combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian)); + combined.append(ByteVector::fromULongLong(data.size(), d->endianness == BigEndian)); combined.append(data); if((data.size() & 0x01) != 0) combined.append('\x00'); diff --git a/taglib/dsf/dsffile.cpp b/taglib/dsf/dsffile.cpp index 35951594..e949b89b 100644 --- a/taglib/dsf/dsffile.cpp +++ b/taglib/dsf/dsffile.cpp @@ -46,8 +46,8 @@ public: FilePrivate &operator=(const FilePrivate &) = delete; const ID3v2::FrameFactory *ID3v2FrameFactory; - long long fileSize = 0; - long long metadataOffset = 0; + unsigned long long fileSize = 0; + unsigned long long metadataOffset = 0; std::unique_ptr properties; std::unique_ptr tag; }; @@ -116,17 +116,17 @@ bool DSF::File::save(ID3v2::Version version) // Three things must be updated: the file size, the tag data, and the metadata offset if(d->tag->isEmpty()) { - long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize; + unsigned long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize; // Update the file size if(d->fileSize != newFileSize) { - insert(ByteVector::fromLongLong(newFileSize, false), 12, 8); + insert(ByteVector::fromULongLong(newFileSize, false), 12, 8); d->fileSize = newFileSize; } // Update the metadata offset to 0 since there is no longer a tag if(d->metadataOffset) { - insert(ByteVector::fromLongLong(0ULL, false), 20, 8); + insert(ByteVector::fromULongLong(0ULL, false), 20, 8); d->metadataOffset = 0; } @@ -136,19 +136,19 @@ bool DSF::File::save(ID3v2::Version version) else { ByteVector tagData = d->tag->render(version); - long long newMetadataOffset = d->metadataOffset ? d->metadataOffset : d->fileSize; - long long newFileSize = newMetadataOffset + tagData.size(); - long long oldTagSize = d->fileSize - newMetadataOffset; + unsigned long long newMetadataOffset = d->metadataOffset ? d->metadataOffset : d->fileSize; + unsigned long long newFileSize = newMetadataOffset + tagData.size(); + unsigned long long oldTagSize = d->fileSize - newMetadataOffset; // Update the file size if(d->fileSize != newFileSize) { - insert(ByteVector::fromLongLong(newFileSize, false), 12, 8); + insert(ByteVector::fromULongLong(newFileSize, false), 12, 8); d->fileSize = newFileSize; } // Update the metadata offset if(d->metadataOffset != newMetadataOffset) { - insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8); + insert(ByteVector::fromULongLong(newMetadataOffset, false), 20, 8); d->metadataOffset = newMetadataOffset; } @@ -175,7 +175,7 @@ void DSF::File::read(AudioProperties::ReadStyle propertiesStyle) return; } - long long dsdHeaderSize = readBlock(8).toLongLong(false); + unsigned long long dsdHeaderSize = readBlock(8).toULongLong(false); // Integrity check if(dsdHeaderSize != 28) { @@ -184,16 +184,16 @@ void DSF::File::read(AudioProperties::ReadStyle propertiesStyle) return; } - d->fileSize = readBlock(8).toLongLong(false); + d->fileSize = readBlock(8).toULongLong(false); // File is malformed or corrupted, allow trailing garbage - if(d->fileSize > length()) { + if(d->fileSize > static_cast(length())) { debug("DSF::File::read() -- File is corrupted wrong length"); setValid(false); return; } - d->metadataOffset = readBlock(8).toLongLong(false); + d->metadataOffset = readBlock(8).toULongLong(false); // File is malformed or corrupted if(d->metadataOffset > d->fileSize) { @@ -210,7 +210,7 @@ void DSF::File::read(AudioProperties::ReadStyle propertiesStyle) return; } - long long fmtHeaderSize = readBlock(8).toLongLong(false); + unsigned long long fmtHeaderSize = readBlock(8).toULongLong(false); if(fmtHeaderSize != 52) { debug("DSF::File::read() -- File is corrupted, wrong FMT header size"); setValid(false);