From 810a0afe1e9bd14e4393a73bf6c299b25745dbc5 Mon Sep 17 00:00:00 2001 From: Richard Weickelt Date: Tue, 24 Nov 2020 01:14:28 +0100 Subject: Fix crash when calling hasOwnProperty() on proxy object Property pointer p needs to be checked for nullptr value in QV4::ProxyObject::virtualGetOwnProperty(). This can happen when calling hasOwnProperty() or propertyIsEnumerable(). Fixes: QTBUG-88786 Change-Id: I43da58fed4d8656f9187213f7317f17398739e34 Reviewed-by: Ulf Hermann (cherry picked from commit 9b321a34490cd17c0eb043b69bd7c9d8d8f513d5) Reviewed-by: Richard Weickelt --- src/qml/jsruntime/qv4proxy.cpp | 10 ++++--- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 31 +++++++++++++++++++++- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp index 24676ffd00..1505eae426 100644 --- a/src/qml/jsruntime/qv4proxy.cpp +++ b/src/qml/jsruntime/qv4proxy.cpp @@ -265,9 +265,9 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property ScopedProperty targetDesc(scope); PropertyAttributes targetAttributes = target->getOwnProperty(id, targetDesc); if (trapResult->isUndefined()) { - p->value = Encode::undefined(); - if (targetAttributes == Attr_Invalid) { + if (p) p->value = Encode::undefined(); + if (targetAttributes == Attr_Invalid) { return Attr_Invalid; } if (!targetAttributes.isConfigurable() || !target->isExtensible()) { @@ -295,8 +295,10 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property } } - p->value = resultDesc->value; - p->set = resultDesc->set; + if (p) { + p->value = resultDesc->value; + p->set = resultDesc->set; + } return resultAttributes; } diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 1e10841430..3a9d1bfb4c 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -382,7 +382,7 @@ private slots: void semicolonAfterProperty(); void hugeStack(); void variantConversionMethod(); - + void proxyHandlerTraps(); void gcCrashRegressionTest(); private: @@ -9306,6 +9306,35 @@ void tst_qqmlecmascript::variantConversionMethod() QCOMPARE(obj.funcCalled, QLatin1String("QModelIndex")); } +void tst_qqmlecmascript::proxyHandlerTraps() +{ + const QString expression = QStringLiteral(R"SNIPPET( + (function(){ + const target = { + prop: 47 + }; + const handler = { + getOwnPropertyDescriptor(target, prop) { + return { configurable: true, enumerable: true, value: 47 }; + } + }; + const proxy = new Proxy(target, handler); + + // QTBUG-88786 + if (!proxy.propertyIsEnumerable("prop")) + throw Error("FAIL: propertyisEnumerable"); + if (!proxy.hasOwnProperty("prop")) + throw Error("FAIL: hasOwnProperty"); + + return "SUCCESS"; + })() + )SNIPPET"); + + QJSEngine engine; + QJSValue value = engine.evaluate(expression); + QVERIFY(value.isString() && value.toString() == QStringLiteral("SUCCESS")); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" -- cgit v1.2.3