QDataStream: adjust containers' deserialization in transaction mode
If an error occurs during the transaction, we should prevent the containers from being successfully read. So, check the status of the stream before reading the container, because the deserialization procedure temporarily resets it on entry. Task-number: QTBUG-54022 Change-Id: Ie955c2fa3e449374f0f8403f00e487efa2bfdaf3 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
9467bdc909
commit
902a5e7aaa
@ -63,6 +63,9 @@ template <class Key, class T> class QMap;
|
||||
|
||||
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
|
||||
class QDataStreamPrivate;
|
||||
namespace QtPrivate {
|
||||
class StreamStateSaver;
|
||||
}
|
||||
class Q_CORE_EXPORT QDataStream
|
||||
{
|
||||
public:
|
||||
@ -192,6 +195,7 @@ private:
|
||||
Status q_status;
|
||||
|
||||
int readBlock(char *data, int len);
|
||||
friend class QtPrivate::StreamStateSaver;
|
||||
};
|
||||
|
||||
namespace QtPrivate {
|
||||
@ -201,6 +205,7 @@ class StreamStateSaver
|
||||
public:
|
||||
inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
|
||||
{
|
||||
if (!stream->dev || !stream->dev->isTransactionStarted())
|
||||
stream->resetStatus();
|
||||
}
|
||||
inline ~StreamStateSaver()
|
||||
|
@ -2750,14 +2750,21 @@ void tst_QDataStream::status_QBitArray()
|
||||
}
|
||||
|
||||
#define MAP_TEST(byteArray, initialStatus, expectedStatus, expectedHash) \
|
||||
for (bool inTransaction = false;; inTransaction = true) { \
|
||||
{ \
|
||||
QByteArray ba = byteArray; \
|
||||
QDataStream stream(&ba, QIODevice::ReadOnly); \
|
||||
if (inTransaction) \
|
||||
stream.startTransaction(); \
|
||||
stream.setStatus(initialStatus); \
|
||||
stream >> hash; \
|
||||
QCOMPARE((int)stream.status(), (int)expectedStatus); \
|
||||
if (!inTransaction || stream.commitTransaction()) { \
|
||||
QCOMPARE(hash.size(), expectedHash.size()); \
|
||||
QCOMPARE(hash, expectedHash); \
|
||||
} else { \
|
||||
QVERIFY(hash.isEmpty()); \
|
||||
} \
|
||||
} \
|
||||
{ \
|
||||
QByteArray ba = byteArray; \
|
||||
@ -2766,11 +2773,20 @@ void tst_QDataStream::status_QBitArray()
|
||||
for (; it != expectedHash.constEnd(); ++it) \
|
||||
expectedMap.insert(it.key(), it.value()); \
|
||||
QDataStream stream(&ba, QIODevice::ReadOnly); \
|
||||
if (inTransaction) \
|
||||
stream.startTransaction(); \
|
||||
stream.setStatus(initialStatus); \
|
||||
stream >> map; \
|
||||
QCOMPARE((int)stream.status(), (int)expectedStatus); \
|
||||
if (!inTransaction || stream.commitTransaction()) { \
|
||||
QCOMPARE(map.size(), expectedMap.size()); \
|
||||
QCOMPARE(map, expectedMap); \
|
||||
} else { \
|
||||
QVERIFY(map.isEmpty()); \
|
||||
} \
|
||||
} \
|
||||
if (inTransaction) \
|
||||
break; \
|
||||
}
|
||||
|
||||
void tst_QDataStream::status_QHash_QMap()
|
||||
@ -2815,14 +2831,21 @@ void tst_QDataStream::status_QHash_QMap()
|
||||
}
|
||||
|
||||
#define LIST_TEST(byteArray, initialStatus, expectedStatus, expectedList) \
|
||||
for (bool inTransaction = false;; inTransaction = true) { \
|
||||
{ \
|
||||
QByteArray ba = byteArray; \
|
||||
QDataStream stream(&ba, QIODevice::ReadOnly); \
|
||||
if (inTransaction) \
|
||||
stream.startTransaction(); \
|
||||
stream.setStatus(initialStatus); \
|
||||
stream >> list; \
|
||||
QCOMPARE((int)stream.status(), (int)expectedStatus); \
|
||||
if (!inTransaction || stream.commitTransaction()) { \
|
||||
QCOMPARE(list.size(), expectedList.size()); \
|
||||
QCOMPARE(list, expectedList); \
|
||||
} else { \
|
||||
QVERIFY(list.isEmpty()); \
|
||||
} \
|
||||
} \
|
||||
{ \
|
||||
LinkedList expectedLinkedList; \
|
||||
@ -2830,11 +2853,17 @@ void tst_QDataStream::status_QHash_QMap()
|
||||
expectedLinkedList << expectedList.at(i); \
|
||||
QByteArray ba = byteArray; \
|
||||
QDataStream stream(&ba, QIODevice::ReadOnly); \
|
||||
if (inTransaction) \
|
||||
stream.startTransaction(); \
|
||||
stream.setStatus(initialStatus); \
|
||||
stream >> linkedList; \
|
||||
QCOMPARE((int)stream.status(), (int)expectedStatus); \
|
||||
if (!inTransaction || stream.commitTransaction()) { \
|
||||
QCOMPARE(linkedList.size(), expectedLinkedList.size()); \
|
||||
QCOMPARE(linkedList, expectedLinkedList); \
|
||||
} else { \
|
||||
QVERIFY(linkedList.isEmpty()); \
|
||||
} \
|
||||
} \
|
||||
{ \
|
||||
Vector expectedVector; \
|
||||
@ -2842,11 +2871,20 @@ void tst_QDataStream::status_QHash_QMap()
|
||||
expectedVector << expectedList.at(i); \
|
||||
QByteArray ba = byteArray; \
|
||||
QDataStream stream(&ba, QIODevice::ReadOnly); \
|
||||
if (inTransaction) \
|
||||
stream.startTransaction(); \
|
||||
stream.setStatus(initialStatus); \
|
||||
stream >> vector; \
|
||||
QCOMPARE((int)stream.status(), (int)expectedStatus); \
|
||||
if (!inTransaction || stream.commitTransaction()) { \
|
||||
QCOMPARE(vector.size(), expectedVector.size()); \
|
||||
QCOMPARE(vector, expectedVector); \
|
||||
} else { \
|
||||
QVERIFY(vector.isEmpty()); \
|
||||
} \
|
||||
} \
|
||||
if (inTransaction) \
|
||||
break; \
|
||||
}
|
||||
|
||||
void tst_QDataStream::status_QLinkedList_QList_QVector()
|
||||
|
Loading…
Reference in New Issue
Block a user