diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-23 10:26:15 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-05-23 08:48:04 +0000 |
commit | eaec83583fff3e3bf431f6179936b84f4acca553 (patch) | |
tree | 2dc06fd396a15436ce53b51803a55262def40256 | |
parent | 1aecb24682075cbb99f21a367c399387b12257d0 (diff) |
Fix crash when modifying objects used as prototypes
Changing the prototype of an object back and forth leads to a
'cyclic' reference in the internal class transition tables. If
one of those objects then gets a new property, we would get an
infinite stack recursion trying to update the internal class IDs
of the classes using this prototype.
Fixed by skipping protochanges and vtable changes in the update
code. That's ok, as those classes will always be reached through
other paths from the empty class.
Task-number: QTBUG-68369
Change-Id: Ie54ca5171a92f8e8b146a91376e435478ff70185
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 18 |
2 files changed, 20 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 9da854e7d7..3bfcf358bf 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -533,6 +533,8 @@ void InternalClass::updateInternalClassIdRecursive() id = engine->newInternalClassId(); for (auto &t : transitions) { Q_ASSERT(t.lookup); + if (t.flags == InternalClassTransition::VTableChange || t.flags == InternalClassTransition::PrototypeChange) + continue; t.lookup->updateInternalClassIdRecursive(); } } diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index f862cdb048..c3a3926144 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -205,6 +205,8 @@ private slots: void scriptScopes(); + void protoChanges_QTBUG68369(); + signals: void testSignal(); }; @@ -4157,6 +4159,22 @@ void tst_QJSEngine::scriptScopes() QCOMPARE(use.toInt(), 42); } +void tst_QJSEngine::protoChanges_QTBUG68369() +{ + QJSEngine engine; + QJSValue ok = engine.evaluate( + "var o = { x: true };" + "var p1 = {};" + "var p2 = {};" + "o.__proto__ = p1;" + "o.__proto__ = p2;" + "o.__proto__ = p1;" + "p1.y = true;" + "o.y" + ); + QVERIFY(ok.toBool() == true); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" |