aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-06-20 16:09:12 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-06-22 08:17:10 +0200
commit00af216756cc975d0ac1e8861364848eed15cb2d (patch)
treeefe8f6a96b890127a3d420ffbd4af0934ce55a00
parentc9dc600bd1365aa9ccb624ff752162d75e3a9e7d (diff)
QmlCompiler: Disable writing into function arguments
We cannot do this in a safe way in 6.3. Fixes: QTBUG-104462 Change-Id: I2c2cc0f526d68c6d9be151f5bc9f21b4a3ae24fe Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp5
-rw-r--r--src/qmlcompiler/qqmljscodegenerator_p.h5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/javaScriptArgument.qml33
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp16
5 files changed, 59 insertions, 1 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index 11fa085d0a..e5f2da7a22 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -586,8 +586,11 @@ void QQmlJSCodeGenerator::generate_LoadReg(int reg)
void QQmlJSCodeGenerator::generate_StoreReg(int reg)
{
INJECT_TRACE_INFO(generate_StoreReg);
-
Q_ASSERT(m_state.accumulatorIn.isValid());
+
+ if (isArgument(reg))
+ reject(u"writing into a function argument"_qs);
+
const QString var = registerVariable(reg);
m_body.setWriteRegister(var);
if (var.isEmpty())
diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h
index a363629924..1048623bff 100644
--- a/src/qmlcompiler/qqmljscodegenerator_p.h
+++ b/src/qmlcompiler/qqmljscodegenerator_p.h
@@ -347,6 +347,11 @@ private:
return m_typeResolver->jsGlobalObject()->property(u"Math"_qs).type();
}
+ bool isArgument(int registerIndex) const
+ {
+ return registerIndex >= QV4::CallData::OffsetCount && registerIndex < firstRegisterIndex();
+ }
+
int firstRegisterIndex() const
{
return QV4::CallData::OffsetCount + m_function->argumentTypes.count();
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 5dc2423a62..c11c537715 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -88,6 +88,7 @@ set(qml_files
interactive.qml
interceptor.qml
isnan.qml
+ javaScriptArgument.qml
jsMathObject.qml
jsimport.qml
jsmoduleimport.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/javaScriptArgument.qml b/tests/auto/qml/qmlcppcodegen/data/javaScriptArgument.qml
new file mode 100644
index 0000000000..f52325e915
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/javaScriptArgument.qml
@@ -0,0 +1,33 @@
+import QtQml
+
+QtObject {
+ function absMinusOne(amount: real) : real {
+ // Access it before the condition below, to make sure we still get the original
+ var minusOne = amount !== 0 ? -1 : 0;
+
+ // The condition causes the original arguemnt to be overwritten rather than a new
+ // register to be allocated
+ if (amount < 0)
+ amount = -amount;
+
+ return amount + minusOne;
+ }
+
+ property real a: absMinusOne(-5)
+ property real b: absMinusOne(10)
+
+ function stringMinusOne(amount: real) : string {
+ // Access it before the condition below, to make sure we still get the original
+ var minusOne = amount !== 0 ? -1 : 0;
+
+ // The condition causes the original arguemnt to be overwritten rather than a new
+ // register to be allocated
+ if (amount < 0)
+ amount = -amount + "t";
+
+ return amount + minusOne;
+ }
+
+ property string c: stringMinusOne(-5)
+ property string d: stringMinusOne(10)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 5fcf5430ed..3d5d5ae37d 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -130,6 +130,7 @@ private slots:
void fromBoolValue();
void invisibleTypes();
void functionTakingVar();
+ void javaScriptArgument();
};
void tst_QmlCppCodegen::simpleBinding()
@@ -2002,6 +2003,21 @@ void tst_QmlCppCodegen::functionTakingVar()
QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
}
+void tst_QmlCppCodegen::javaScriptArgument()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/TestTypes/javaScriptArgument.qml"_qs));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a").toDouble(), 4.0);
+ QCOMPARE(o->property("b").toDouble(), 9.0);
+ QCOMPARE(o->property("c").toString(), u"5t-1"_qs);
+ QCOMPARE(o->property("d").toString(), u"9"_qs);
+}
+
void tst_QmlCppCodegen::runInterpreted()
{
#ifdef Q_OS_ANDROID