From bc00353cffbfe0f74b602a16452f2e7bcd588152 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 8 Apr 2019 16:57:30 +0200 Subject: Detect and reject cyclic aliases Previously those would result in infinite recursion. Fixes: QTBUG-74867 Change-Id: I6c0043b43e72fe7bc3a2a139ca600af2d5bca5ad Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlpropertycachecreator_p.h | 40 ++++++++++++++++------ .../qml/qqmllanguage/data/cyclicAlias.errors.txt | 1 + tests/auto/qml/qqmllanguage/data/cyclicAlias.qml | 5 +++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt create mode 100644 tests/auto/qml/qqmllanguage/data/cyclicAlias.qml diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h index 6bee599c0a..074dc98648 100644 --- a/src/qml/compiler/qqmlpropertycachecreator_p.h +++ b/src/qml/compiler/qqmlpropertycachecreator_p.h @@ -692,11 +692,6 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator::property const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion, QQmlPropertyData::Flags *propertyFlags) { - const int targetObjectIndex = objectForId(component, alias.targetObjectId); - Q_ASSERT(targetObjectIndex >= 0); - - const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex); - *type = 0; bool writable = false; bool resettable = false; @@ -704,11 +699,36 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator::property propertyFlags->isAlias = true; if (alias.aliasToLocalAlias) { - auto targetAlias = targetObject.aliasesBegin(); - for (uint i = 0; i < alias.localAliasIndex; ++i) - ++targetAlias; - return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags); - } else if (alias.encodedMetaPropertyIndex == -1) { + const QV4::CompiledData::Alias *lastAlias = &alias; + QVarLengthArray seenAliases({lastAlias}); + + do { + const CompiledObject *targetObject = objectContainer->objectAt( + objectForId(component, lastAlias->targetObjectId)); + Q_ASSERT(targetObject); + + auto nextAlias = targetObject->aliasesBegin(); + for (uint i = 0; i < lastAlias->localAliasIndex; ++i) + ++nextAlias; + + const QV4::CompiledData::Alias *targetAlias = &(*nextAlias); + if (seenAliases.contains(targetAlias)) { + return QQmlCompileError(targetAlias->location, + QQmlPropertyCacheCreatorBase::tr("Cyclic alias")); + } + + seenAliases.append(targetAlias); + lastAlias = targetAlias; + } while (lastAlias->aliasToLocalAlias); + + return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags); + } + + const int targetObjectIndex = objectForId(component, alias.targetObjectId); + Q_ASSERT(targetObjectIndex >= 0); + const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex); + + if (alias.encodedMetaPropertyIndex == -1) { Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject); auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex); if (!typeRef) { diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt new file mode 100644 index 0000000000..46951ef69f --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt @@ -0,0 +1 @@ +4:5:Cyclic alias diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml new file mode 100644 index 0000000000..23129e210d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml @@ -0,0 +1,5 @@ +import QtQml 2.2 +QtObject { + id: o + property alias t: o.t +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index dea7c6c7ee..f7198415a2 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -612,6 +612,7 @@ void tst_qqmllanguage::errors_data() QTest::newRow("badCompositeRegistration.1") << "badCompositeRegistration.1.qml" << "badCompositeRegistration.1.errors.txt" << false; QTest::newRow("badCompositeRegistration.2") << "badCompositeRegistration.2.qml" << "badCompositeRegistration.2.errors.txt" << false; + QTest::newRow("cyclicAlias") << "cyclicAlias.qml" << "cyclicAlias.errors.txt" << false; } -- cgit v1.2.3