diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-06-20 16:09:12 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-06-22 08:17:10 +0200 |
commit | 00af216756cc975d0ac1e8861364848eed15cb2d (patch) | |
tree | efe8f6a96b890127a3d420ffbd4af0934ce55a00 | |
parent | c9dc600bd1365aa9ccb624ff752162d75e3a9e7d (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.cpp | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator_p.h | 5 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/javaScriptArgument.qml | 33 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 16 |
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 |