From bedf0367ac580a2e73712be2f4207bb6af9f0226 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 1 Apr 2016 08:32:37 +0200 Subject: 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 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) --- src/corelib/kernel/qmetatype.h | 2 +- .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 27 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 3b8f8e7166..899a51173e 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -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) diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index c91bb21399..f2f3baae6b 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -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 mapping; + QString name = QString::fromLatin1("Seven"); + mapping.insert(name, Q_NULLPTR); + + QVariant variant = QVariant::fromValue(mapping); + + QAssociativeIterable iterable = variant.value(); + 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" -- cgit v1.2.3