mirror of
https://github.com/taglib/taglib.git
synced 2026-05-25 13:08:55 -04:00
Fix DSD/DSF signed integer issues (#1332)
This commit is contained in:
@@ -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');
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user