Fix endianness bug in PCX reader on big endian architectures

When reading from a sequential device, the peekHeader() method in
the PCX readers reads the header its defined little endian into
arch-specific endianness for multibyte types.

Being a "peek" method, it then it tries to push back the bytes into
the device after reading for its next use, but it doesn’t convert
multibyte types correctly from arch-specifice endianness to the
initial little endian format.

Subsequent reading of the data from the device will thus lead to
incorrect values for multibyte types on the next use.

This patch reuses the same technique as the TGA reader to read the
whole header as bytes before deserializing it, so that the bytes
can be pushed back into the sequential device in the same order.
This commit is contained in:
Aurélien COUDERC 2024-09-22 01:30:58 +02:00
parent 46f7b90ce6
commit ae641f7e94

View File

@ -266,29 +266,30 @@ PCXHEADER::PCXHEADER()
bool peekHeader(QIODevice *d, PCXHEADER& h)
{
qint64 pos = 0;
if (!d->isSequential()) {
pos = d->pos();
qint64 oldPos = d->pos();
QByteArray head = d->read(sizeof(PCXHEADER));
int readBytes = head.size();
if (d->isSequential()) {
for (int pos = readBytes -1; pos >= 0; --pos) {
d->ungetChar(head[pos]);
}
} else {
d->seek(oldPos);
}
if (readBytes < sizeof(PCXHEADER)) {
return false;
}
auto ok = false;
{ // datastream is destroyed before working on device
QDataStream ds(d);
QDataStream ds(head);
ds.setByteOrder(QDataStream::LittleEndian);
ds >> h;
ok = ds.status() == QDataStream::Ok && h.isValid();
}
if (!d->isSequential()) {
return d->seek(pos) && ok;
}
// sequential device undo
auto head = reinterpret_cast<char*>(&h);
auto readBytes = sizeof(h);
while (readBytes > 0) {
d->ungetChar(head[readBytes-- - 1]);
}
return ok;
}