QVariant: Fix flags for type-erased associative iterator key

The flags here are passed to a private QVariant constructor, and they
really represent a boolean - IsPointer or not.

Because the flag for the key_type was incorrectly populated with the
flag for the value_type, memory would be corrupted when using a mapping
type whose value_type is a pointer, but whose key type was not, such as

  QMap<QString, int*>

This typo has been there since the concept was introduced in commit
v5.2.0-alpha1~807 (Add container access functionality for associative
containers in QVariant., 2013-04-05).

Task-number: QTBUG-52246
Change-Id: I9ecb13c603015eed2dc2ca43947fa0ecd6be8b5a
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Stephen Kelly 2016-04-01 08:32:37 +02:00
parent ad864ef194
commit bedf0367ac
2 changed files with 28 additions and 1 deletions

View File

@ -1226,7 +1226,7 @@ public:
inline void destroyIter() { _destroyIter(&_iterator); }
inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_value); }
inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); }
inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
inline void find(const VariantData &key)

View File

@ -280,6 +280,8 @@ private slots:
void compareSanity_data();
void compareSanity();
void accessSequentialContainerKey();
private:
void dataStream_data(QDataStream::Version version);
void loadQVariantFromDataStream(QDataStream::Version version);
@ -4733,5 +4735,30 @@ void tst_QVariant::compareSanity()
}
}
void tst_QVariant::accessSequentialContainerKey()
{
QString nameResult;
{
QMap<QString, QObject*> mapping;
QString name = QString::fromLatin1("Seven");
mapping.insert(name, Q_NULLPTR);
QVariant variant = QVariant::fromValue(mapping);
QAssociativeIterable iterable = variant.value<QAssociativeIterable>();
QAssociativeIterable::const_iterator iit = iterable.begin();
const QAssociativeIterable::const_iterator end = iterable.end();
for ( ; iit != end; ++iit) {
nameResult += iit.key().toString();
}
} // Destroy mapping
// Regression test for QTBUG-52246 - no memory corruption/double deletion
// of the string key.
QCOMPARE(nameResult, QStringLiteral("Seven"));
}
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"