Fix DSD/DSF signed integer issues (#1332)

This commit is contained in:
Urs Fleisch
2026-04-20 15:08:37 +02:00
committed by GitHub
parent d466b72eea
commit a64e7543f8
2 changed files with 42 additions and 42 deletions

View File

@@ -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<unsigned long long>(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<long long>(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<int>(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<unsigned long long>(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<long long>(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<int>(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<unsigned long long>(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<long long>(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<int>(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');

View File

@@ -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> properties;
std::unique_ptr<ID3v2::Tag> 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<unsigned long long>(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);