diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-10-06 10:09:01 +0200 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-10-07 07:41:21 +0200 |
| commit | f5e34266ea15c6e44e9816f01f4e627d5f038f0c (patch) | |
| tree | 4e898b2d1f37f8c19602ed6e4381bb6b30989121 /src/qmlcompiler | |
| parent | ba56f1e4638f9752903d587129b0474e845ce416 (diff) | |
QmlCompiler: Fix write access to QVariantMap
Without this, it tries to resolve the metaObject of QVariantMap, which
crashes.
Amends commit cca07aa78841f2d743f0b4d933abb0dd66f0b948.
Fixes: QTBUG-139626
Pick-to: 6.10 6.8
Change-Id: Id747429ed0d558932b9a6cb8f59e3740982efb56
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Diffstat (limited to 'src/qmlcompiler')
| -rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 52 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljscodegenerator_p.h | 5 |
2 files changed, 48 insertions, 9 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 464e92ee37..9c2abc3450 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -1472,7 +1472,7 @@ void QQmlJSCodeGenerator::generate_GetLookup(int index) generate_GetLookupHelper(index); } -QString QQmlJSCodeGenerator::generateVariantMapLookup( +QString QQmlJSCodeGenerator::generateVariantMapGetLookup( const QString &map, const int nameIndex) { const QString mapLookup = map @@ -1483,6 +1483,18 @@ QString QQmlJSCodeGenerator::generateVariantMapLookup( + u";\n"_s; } +QString QQmlJSCodeGenerator::generateVariantMapSetLookup( + const QString &map, const int nameIndex, + const QQmlJSScope::ConstPtr &property, const QString &variableIn) +{ + const QString mapLookup = map + + u"["_s + QQmlJSUtils::toLiteral(m_jsUnitGenerator->lookupName(nameIndex)) + u"]"_s; + + return mapLookup + u" = "_s + + conversion(property, m_typeResolver->varType(), variableIn) + + u";\n"_s; +} + void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) { if (m_state.accumulatorOut().isMethod()) @@ -1628,7 +1640,7 @@ void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) REJECT(u"access to 'length' property of sequence wrapped in non-sequence"_s); } } else if (accumulatorIn.isStoredIn(m_typeResolver->variantMapType())) { - m_body += generateVariantMapLookup(m_state.accumulatorVariableIn, index); + m_body += generateVariantMapGetLookup(m_state.accumulatorVariableIn, index); } else { if (m_state.isRegisterAffectedBySideEffects(Accumulator)) REJECT(u"reading from a value that's potentially affected by side effects"_s); @@ -1639,7 +1651,7 @@ void QQmlJSCodeGenerator::generate_GetLookupHelper(int index) m_jsUnitGenerator->lookupName(index))); if (scope.contains(m_typeResolver->variantMapType())) { - m_body += generateVariantMapLookup( + m_body += generateVariantMapGetLookup( u"(*static_cast<const QVariantMap *>("_s + inputContentPointer + u"))"_s, index); return; @@ -1699,6 +1711,15 @@ void QQmlJSCodeGenerator::generate_StoreProperty(int nameIndex, int baseReg) REJECT(u"StoreProperty"_s); } +// TODO: This shouldn't be necessary. If the content can be stored directly, then it should +// be stored and used directly. If it cannot be stored directly, it should be stored +// as QVariant, but then we cannot dereference the content pointer either. +static QString derefContentPointer(const QString &contentPointer) +{ + Q_ASSERT(contentPointer.startsWith(u'&') || contentPointer[0].isLetterOrNumber()); + return contentPointer.startsWith(u'&') ? contentPointer.mid(1) : (u'*' + contentPointer); +} + void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) { INJECT_TRACE_INFO(generate_SetLookup); @@ -1707,8 +1728,9 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) const QQmlJSScope::ConstPtr valueType = m_state.accumulatorIn().storedType(); const QQmlJSRegisterContent property = m_state.readAccumulator(); Q_ASSERT(property.isConversion()); - const QQmlJSScope::ConstPtr originalScope - = m_typeResolver->original(property.conversionResultScope()).containedType(); + const QQmlJSRegisterContent original + = m_typeResolver->original(property.conversionResultScope()); + const QQmlJSScope::ConstPtr originalScope = original.containedType(); if (property.storedType().isNull()) { REJECT(u"SetLookup. Could not find property " @@ -1758,9 +1780,7 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) // We can resize without write back on a list property because it's actually a reference. m_body += u"const int begin = "_s + object + u".count(&" + object + u");\n"_s; - m_body += u"const int end = "_s - + (variableIn.startsWith(u'&') ? variableIn.mid(1) : (u'*' + variableIn)) - + u";\n"_s; + m_body += u"const int end = "_s + derefContentPointer(variableIn) + u";\n"_s; m_body += u"for (int i = begin; i < end; ++i)\n"_s; m_body += u" "_s + object + u".append(&"_s + object + u", nullptr);\n"_s; m_body += u"for (int i = begin; i > end; --i)\n"_s; @@ -1770,10 +1790,26 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) } case QQmlJSScope::AccessSemantics::Value: { const QQmlJSRegisterContent base = registerType(baseReg); + if (base.isStoredIn(m_typeResolver->variantMapType())) { + m_body += generateVariantMapSetLookup( + registerVariable(baseReg), index, property.storedType(), + derefContentPointer(variableIn)); + generateWriteBack(baseReg); + break; + } const QString baseContentPointer = resolveValueTypeContentPointer( originalScope, base, object, u"TypeError: Value is %1 and could not be converted to an object"_s); + if (original.contains(m_typeResolver->variantMapType())) { + m_body += generateVariantMapSetLookup( + u"(*static_cast<const QVariantMap *>("_s + + baseContentPointer + u"))"_s, index, property.storedType(), + derefContentPointer(variableIn)); + generateWriteBack(baseReg); + break; + } + const QString lookup = u"aotContext->setValueLookup("_s + indexString + u", "_s + baseContentPointer + u", "_s + variableIn + u')'; diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h index ce160bf4f3..46da0bb61c 100644 --- a/src/qmlcompiler/qqmljscodegenerator_p.h +++ b/src/qmlcompiler/qqmljscodegenerator_p.h @@ -366,7 +366,10 @@ private: const QQmlJSMetaMethod &ctor, const QList<QQmlJSRegisterContent> &argumentTypes, const QStringList &arguments, const QString &metaType, const QString &metaObject); - QString generateVariantMapLookup(const QString &map, const int nameIndex); + QString generateVariantMapGetLookup(const QString &map, const int nameIndex); + QString generateVariantMapSetLookup( + const QString &map, const int nameIndex, const QQmlJSScope::ConstPtr &property, + const QString &variableIn); QQmlJSRegisterContent originalType(QQmlJSRegisterContent tracked) { |
