aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-05-17 14:40:00 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-06-01 15:06:06 +0200
commitc41fe1592fea0afa805d6b1ed07791acc5113379 (patch)
tree64729e596943a19db5fb31410cf48431bdd46105
parentec1dc0ed933a8270ec59ff69c41987862398ea2d (diff)
QmlCompiler: Detect non-integral values when accessing QQmlListProperty
Fixes: QTBUG-103560 Change-Id: Ifcc73baf7f79e30f6e83ff3e500dd39f95790bfe Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> (cherry picked from commit 4a10e1d84ac948fb9a50cd2e44fcbeaef972e5ea)
-rw-r--r--src/qml/common/qjsnumbercoercion.h4
-rw-r--r--src/qmlcompiler/qqmljscodegenerator.cpp22
-rw-r--r--src/qmlcompiler/qqmljstyperesolver.cpp5
-rw-r--r--src/qmlcompiler/qqmljstyperesolver_p.h1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listIndices.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp4
6 files changed, 39 insertions, 5 deletions
diff --git a/src/qml/common/qjsnumbercoercion.h b/src/qml/common/qjsnumbercoercion.h
index 2517442bb6..0e233747ff 100644
--- a/src/qml/common/qjsnumbercoercion.h
+++ b/src/qml/common/qjsnumbercoercion.h
@@ -48,6 +48,10 @@ QT_BEGIN_NAMESPACE
class QJSNumberCoercion
{
public:
+ static constexpr bool isInteger(double d) {
+ return equals(d, d) && equals(static_cast<int>(d), d);
+ }
+
static constexpr int toInteger(double d) {
if (!equals(d, d))
return 0;
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp
index cd325ae971..11fa085d0a 100644
--- a/src/qmlcompiler/qqmljscodegenerator.cpp
+++ b/src/qmlcompiler/qqmljscodegenerator.cpp
@@ -812,6 +812,15 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base)
const QString baseName = use(registerVariable(base));
const QString indexName = use(m_state.accumulatorVariableIn);
+ const QString voidAssignment = u" "_qs + m_state.accumulatorVariableOut + u" = "_qs +
+ conversion(m_typeResolver->globalType(m_typeResolver->voidType()),
+ m_state.accumulatorOut, QString()) + u";\n"_qs;
+
+ if (!m_typeResolver->isIntegral(m_state.accumulatorIn)) {
+ m_body += u"if (!QJSNumberCoercion::isInteger("_qs + indexName + u"))\n"_qs
+ + voidAssignment
+ + u"else "_qs;
+ }
// Our QQmlListProperty only keeps plain QObject*.
const auto valueType = m_typeResolver->valueType(baseType);
const auto elementType = m_typeResolver->globalType(
@@ -824,9 +833,8 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base)
conversion(elementType, m_state.accumulatorOut,
baseName + u".at(&"_qs + baseName + u", "_qs
+ indexName + u')') + u";\n"_qs;
- m_body += u"else\n"_qs;
- m_body += u" "_qs + m_state.accumulatorVariableOut + u" = {}"_qs;
- m_body += u";\n"_qs;
+ m_body += u"else\n"_qs
+ + voidAssignment;
}
void QQmlJSCodeGenerator::generate_StoreElement(int base, int index)
@@ -837,6 +845,7 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index)
m_body.setWriteRegister(QString());
const QQmlJSRegisterContent baseType = registerType(base);
+ const QQmlJSRegisterContent indexType = registerType(index);
if (!m_typeResolver->isNumeric(registerType(index)) || !baseType.isList()) {
reject(u"StoreElement with non-list base type or non-numeric arguments"_qs);
@@ -855,8 +864,11 @@ void QQmlJSCodeGenerator::generate_StoreElement(int base, int index)
const auto elementType = m_typeResolver->globalType(m_typeResolver->genericType(
m_typeResolver->containedType(valueType)));
- m_body += u"if ("_qs + indexName + u" >= 0 && "_qs + indexName
- + u" < "_qs + baseName + u".count(&"_qs + baseName
+ m_body += u"if ("_qs;
+ if (!m_typeResolver->isIntegral(indexType))
+ m_body += u"QJSNumberCoercion::isInteger("_qs + indexName + u") && "_qs;
+ m_body += indexName + u" >= 0 && "_qs
+ + indexName + u" < "_qs + baseName + u".count(&"_qs + baseName
+ u"))\n"_qs;
m_body += u" "_qs + baseName + u".replace(&"_qs + baseName
+ u", "_qs + indexName + u", "_qs;
diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp
index d1e1fa66f8..e38038d79a 100644
--- a/src/qmlcompiler/qqmljstyperesolver.cpp
+++ b/src/qmlcompiler/qqmljstyperesolver.cpp
@@ -255,6 +255,11 @@ bool QQmlJSTypeResolver::isNumeric(const QQmlJSRegisterContent &type) const
return isNumeric(containedType(type));
}
+bool QQmlJSTypeResolver::isIntegral(const QQmlJSRegisterContent &type) const
+{
+ return containedType(type) == m_intType;
+}
+
bool QQmlJSTypeResolver::isPrimitive(const QQmlJSScope::ConstPtr &type) const
{
return type == m_intType || type == m_realType || type == m_floatType || type == m_boolType
diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h
index 491391f801..85daa35cb1 100644
--- a/src/qmlcompiler/qqmljstyperesolver_p.h
+++ b/src/qmlcompiler/qqmljstyperesolver_p.h
@@ -107,6 +107,7 @@ public:
bool isPrimitive(const QQmlJSRegisterContent &type) const;
bool isNumeric(const QQmlJSRegisterContent &type) const;
+ bool isIntegral(const QQmlJSRegisterContent &type) const;
bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const;
bool canConvertFromTo(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const;
diff --git a/tests/auto/qml/qmlcppcodegen/data/listIndices.qml b/tests/auto/qml/qmlcppcodegen/data/listIndices.qml
index b5fda4ef0d..9df172b2e6 100644
--- a/tests/auto/qml/qmlcppcodegen/data/listIndices.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/listIndices.qml
@@ -5,10 +5,18 @@ QtObject {
id: self
property list<QtObject> items
property int numItems: items.length
+ property QtObject fractional: items[2.25]
+ property QtObject negativeZero: items[-1 * 0]
+ property QtObject infinity: items[1 / 0]
+ property QtObject nan: items[1 - "a"]
Component.onCompleted: {
items.length = 3
for (var i = 0; i < 3; ++i)
items[i] = self
+
+ items[2.25] = null
+ items[1 / 0] = self
+ items[1 - "a"] = self
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index bd6fb37677..1e71eaad52 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -1553,6 +1553,10 @@ void tst_QmlCppCodegen::listIndices()
for (int i = 0; i < 3; ++i)
QCOMPARE(list.at(i), o.data());
QCOMPARE(o->property("numItems").toInt(), 3);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data());
+ QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr);
}
void tst_QmlCppCodegen::jsMathObject()