[neon/qt6/qt6-declarative/Neon/release] debian/patches: add qml crash backport as per distro list recommendation

Carlos De Maine null at kde.org
Sun Nov 16 21:55:51 GMT 2025


Git commit f857a9f4edbb676387773ae15abc58938cf3581e by Carlos De Maine.
Committed on 16/11/2025 at 21:55.
Pushed by carlosdem into branch 'Neon/release'.

add qml crash backport as per distro list recommendation

A  +241  -0    debian/patches/0de0b0f.diff
A  +1    -0    debian/patches/series

https://invent.kde.org/neon/qt6/qt6-declarative/-/commit/f857a9f4edbb676387773ae15abc58938cf3581e

diff --git a/debian/patches/0de0b0f.diff b/debian/patches/0de0b0f.diff
new file mode 100644
index 0000000..3f5684d
--- /dev/null
+++ b/debian/patches/0de0b0f.diff
@@ -0,0 +1,241 @@
+From 0de0b0ffdb44d73c605e20f00934dfb44bdf7ad9 Mon Sep 17 00:00:00 2001
+From: Ulf Hermann <ulf.hermann at qt.io>
+Date: Mon, 06 Oct 2025 10:09:01 +0200
+Subject: [PATCH] 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.8
+Change-Id: Id747429ed0d558932b9a6cb8f59e3740982efb56
+Reviewed-by: Olivier De Cannière <olivier.decanniere at qt.io>
+(cherry picked from commit f5e34266ea15c6e44e9816f01f4e627d5f038f0c)
+Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot at qt-project.org>
+---
+
+diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
+index ce50e4c..b8ad569 100644
+--- a/src/qmlcompiler/qqmljscodegenerator.cpp
++++ b/src/qmlcompiler/qqmljscodegenerator.cpp
+@@ -1472,7 +1472,7 @@
+     generate_GetLookupHelper(index);
+ }
+ 
+-QString QQmlJSCodeGenerator::generateVariantMapLookup(
++QString QQmlJSCodeGenerator::generateVariantMapGetLookup(
+         const QString &map, const int nameIndex)
+ {
+     const QString mapLookup = map
+@@ -1483,6 +1483,18 @@
+             + 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 @@
+             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 @@
+                         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 @@
+     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 @@
+     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 @@
+ 
+         // 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 @@
+     }
+     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 ce160bf..46da0bb 100644
+--- a/src/qmlcompiler/qqmljscodegenerator_p.h
++++ b/src/qmlcompiler/qqmljscodegenerator_p.h
+@@ -366,7 +366,10 @@
+             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)
+     {
+diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
+index de7ac4f..c1e5206 100644
+--- a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
++++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
+@@ -7,19 +7,32 @@
+ {
+     Q_OBJECT
+     QML_ELEMENT
+-    Q_PROPERTY(QVariantMap data READ data CONSTANT)
+-    Q_PROPERTY(QList<QVariantMap> many READ many CONSTANT)
++    Q_PROPERTY(QVariantMap data READ data WRITE setData NOTIFY dataChanged)
++    Q_PROPERTY(QList<QVariantMap> many READ many NOTIFY dataChanged)
+ 
+ public:
+     VariantMapLookupFoo(QObject *parent = nullptr) : QObject(parent) { }
+ 
+-private:
+-    QVariantMap data() const { return { { QStringLiteral("value"), 42 } }; }
++    QVariantMap data() const { return m_data; }
++    void setData(const QVariantMap &data)
++    {
++        if (data == m_data)
++            return;
++        m_data = data;
++        emit dataChanged();
++    }
++
+     QList<QVariantMap> many() const
+     {
+         const QVariantMap one = data();
+         return QList<QVariantMap>({one, one, one});
+     }
++
++signals:
++    void dataChanged();
++
++private:
++    QVariantMap m_data;
+ };
+ 
+ 
+diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
+index 45cb0ed..75b4fd0 100644
+--- a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
++++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
+@@ -3,10 +3,28 @@
+ import QtQuick
+ 
+ Item {
++    id: root
+     property int i: moo.data.value
+     property int j: moo.many[1].value
++    property string foo: moo.data.foo
+ 
+     VariantMapLookupFoo {
+         id: moo
++        data: {
++            let result = { value: 42 };
++            switch(root.visible) {
++                case true:
++                    result.foo = "blue";
++                    break;
++                case false:
++                    result.foo = "green";
++                    break;
++            }
++            return result;
++        }
++    }
++
++    function doI() {
++        moo.data.value = i + 1
+     }
+ }
+diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+index 6a9c50c..9f85f64 100644
+--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
++++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+@@ -6097,6 +6097,12 @@
+     QVERIFY(!o.isNull());
+     QCOMPARE(o->property("i"), 42);
+     QCOMPARE(o->property("j"), 42);
++    QCOMPARE(o->property("foo"), u"blue"_s);
++
++    QMetaObject::invokeMethod(o.data(), "doI");
++    QCOMPARE(o->property("i"), 43);
++    QCOMPARE(o->property("j"), 43);
++    QCOMPARE(o->property("foo"), u"blue"_s);
+ }
+ 
+ void tst_QmlCppCodegen::variantReturn()
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..591f3f8
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+0de0b0f.diff


More information about the Neon-commits mailing list