diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index ea7635a58f2..1080079dcfb 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -566,6 +566,11 @@ void QPropertyBindingData::registerWithCurrentlyEvaluatingBinding_helper(Binding { QPropertyBindingDataPointer d{this}; + if (currentState->alreadyCaptureProperties.contains(this)) + return; + else + currentState->alreadyCaptureProperties.push_back(this); + QPropertyObserverPointer dependencyObserver = currentState->binding->allocateDependencyObserver(); Q_ASSERT(QPropertyObserver::ObserverNotifiesBinding == 0); dependencyObserver.setBindingToNotify_unsafe(currentState->binding); diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h index 43bd81061dd..b850fa88326 100644 --- a/src/corelib/kernel/qproperty_p.h +++ b/src/corelib/kernel/qproperty_p.h @@ -144,6 +144,7 @@ struct BindingEvaluationState QPropertyBindingPrivate *binding; BindingEvaluationState *previousState = nullptr; BindingEvaluationState **currentState = nullptr; + QVarLengthArray alreadyCaptureProperties; }; /*! diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 8d6781fa2d1..63cf9c28174 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -99,6 +99,7 @@ private slots: void metaProperty(); void modifyObserverListWhileIterating(); + void noDoubleCapture(); void compatPropertyNoDobuleNotification(); void compatPropertySignals(); @@ -1491,6 +1492,22 @@ void tst_QProperty::modifyObserverListWhileIterating() } } +void tst_QProperty::noDoubleCapture() +{ + QProperty size; + size = 3; + QProperty max; + max.setBinding([&size]() -> int { + // each loop run attempts to capture size + for (int i = 0; i < size; ++i) {} + return size.value(); + }); + auto bindingPriv = QPropertyBindingPrivate::get(max.binding()); + QCOMPARE(bindingPriv->dependencyObserverCount, 1); + size = 4; // should not crash + QCOMPARE(max.value(), 4); +} + class CompatPropertyTester : public QObject { Q_OBJECT