Handle RIFF chunk padding and ignore trailing garbage

This is based on patches by Marc Halbruegge, but those only deal with
read-only cases. The code now also correctly adds padding to RIFF
chunks, and calculates offsets in chunkData taking the padding into
account.

BUG:171957
BUG:175781


git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1003745 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Lukáš Lalinský
2009-07-28 18:29:39 +00:00
parent 834d9d6b23
commit 8636eb749a
5 changed files with 151 additions and 4 deletions

View File

@ -49,6 +49,7 @@ public:
std::vector<ByteVector> chunkNames;
std::vector<uint> chunkOffsets;
std::vector<uint> chunkSizes;
std::vector<char> chunkPadding;
};
////////////////////////////////////////////////////////////////////////////////
@ -101,7 +102,7 @@ ByteVector RIFF::File::chunkData(uint i)
long begin = 12 + 8;
for(uint it = 0; it < i; it++)
begin += 8 + d->chunkSizes[it];
begin += 8 + d->chunkSizes[it] + d->chunkPadding[it];
seek(begin);
@ -128,12 +129,15 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
// Now update the specific chunk
writeChunk(name, data, d->chunkOffsets[i] - 8, d->chunkSizes[i] + 8);
writeChunk(name, data, d->chunkOffsets[i] - 8, d->chunkSizes[i] + d->chunkPadding[i] + 8);
d->chunkSizes[i] = data.size();
d->chunkPadding[i] = (data.size() & 0x01) ? 1 : 0;
// Now update the internal offsets
for(i++; i < d->chunkNames.size(); i++)
d->chunkOffsets[i] += sizeDifference;
d->chunkOffsets[i] = d->chunkOffsets[i-1] + 8 + d->chunkSizes[i-1] + d->chunkPadding[i-1];
return;
}
@ -158,16 +162,38 @@ void RIFF::File::read()
d->size = readBlock(4).toUInt(bigEndian);
d->format = readBlock(4);
while(tell() < length()) {
// + 8: chunk header at least, fix for additional junk bytes
while(tell() + 8 <= length()) {
ByteVector chunkName = readBlock(4);
uint chunkSize = readBlock(4).toUInt(bigEndian);
if(tell() + chunkSize > length()) {
// something wrong
break;
}
d->chunkNames.push_back(chunkName);
d->chunkSizes.push_back(chunkSize);
d->chunkOffsets.push_back(tell());
seek(chunkSize, Current);
// check padding
char paddingSize = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0)) {
// not well formed, re-seek
seek(uPosNotPadded, Beginning);
}
else {
paddingSize = 1;
}
}
d->chunkPadding.push_back(paddingSize);
}
}
@ -177,5 +203,9 @@ void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
ByteVector combined = name;
combined.append(ByteVector::fromUInt(data.size(), d->endianness == BigEndian));
combined.append(data);
if((data.size() & 0x01) != 0) {
// padding
combined.append('\x00');
}
insert(combined, offset, replace);
}