QIODevice: fix data loss when reading large amounts from sequential devices

In certain situations, when reading a large amount of data from
sequential devices with QIODevice::readAll(), content was lost when
passing a qint64 value > QByteArray::MaxSize into QByteArray::resize(),
which takes an int. The result of the conversion to int is either negative or
calculated mod 2^32. In any case, it will at some point be < QByteArray::size(),
which prompts QByteArray to truncate, losing already-read content.

Fix by adding an explicit size check before calling QByteArray::resize().

This shows once more that an API that uses int for sizes is dangerous.
Esp. on 64-bit platforms.

Change-Id: I30fbfad0bf37476c34141b6f3786e7e0fc8e1e74
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Marc Mutz 2015-04-27 10:32:32 +02:00
parent 39683b2980
commit 84b739158d

View File

@ -989,6 +989,10 @@ QByteArray QIODevice::readAll()
// Size is unknown, read incrementally.
qint64 readResult;
do {
if (quint64(readBytes) + QIODEVICE_BUFFERSIZE > QByteArray::MaxSize) {
// If resize would fail, don't read more, return what we have.
break;
}
result.resize(readBytes + QIODEVICE_BUFFERSIZE);
readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE);
if (readResult > 0 || readBytes == 0)