From 679a9972b46b0ebd03444f3c08ce7d3424c494f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=C4=8Cuki=C4=87?= Date: Fri, 7 Dec 2018 23:24:58 +0100 Subject: TextInput: Stop leaking password values to process memory The contents of a deleted QString can still remain in memory and can be accessible by tools that read the raw process memory. The same problem appears when the QString reallocates -- the old buffer gets deleted, but its contents will remain in memory. This means that a TextInput that serves as a password input field can leak parts of the password while the user is entering it (due to reallocation) and the whole password when the TextInput instance is destroyed. With this patch, the contents of the m_text string member variable will be zeroed-out before the TextInput is destructed. This is done only in the cases when the TextInput serves as a password field. Also, this patch reserves the space for 30 characters for m_text when the TextInput is used for password input. This is enough to make sure no reallocation happens in majority of cases as barely anyone uses passwords longer than 30 characters. [ChangeLog][QtQuick][TextInput/security] When the TextInput is used for password input, preallocate a buffer for the string that stores the entered value and zero-out the string on TextInput destruction to avoid leaking sensitive data to process memory Change-Id: I8f1f307b1cfc25ad51f48bae8509a258042a2e7f Reviewed-by: Frederik Gladhorn --- src/quick/items/qquicktextinput.cpp | 6 ++++++ src/quick/items/qquicktextinput_p_p.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index a0ac884fef..aac7137ff3 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1242,6 +1242,12 @@ void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo) d->updateDisplayText(); updateCursorRectangle(); + // If this control is used for password input, we want to minimize + // the possibility of string reallocation not to leak (parts of) + // the password. + if (d->m_echoMode != QQuickTextInput::Normal) + d->m_text.reserve(30); + emit echoModeChanged(echoMode()); } diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index a2e2f0f66d..7965f3d3f4 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -162,6 +162,11 @@ public: ~QQuickTextInputPrivate() { + // If this control is used for password input, we don't want the + // password data to stay in the process memory, therefore we need + // to zero it out + if (m_echoMode != QQuickTextInput::Normal) + m_text.fill(0); } void init(); -- cgit v1.2.3 From 729b1ceb8904a857ba4c804e8a58b9ef4ef7b193 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 18 Jan 2019 14:12:21 +0100 Subject: Correctly scope unwind handlers for try blocks Make sure the unwind handler is always reset when leaving the try block. This exposes a couple of failures in the ECMAScript test suite that were before passing by pure luck. Task-number: QTBUG-72858 Change-Id: I014b1e37c2beff136ecd53a665a2f10933f7e12c Reviewed-by: Ulf Hermann Reviewed-by: Erik Verbruggen --- src/qml/compiler/qv4codegen.cpp | 3 -- tests/auto/qml/ecmascripttests/TestExpectations | 47 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index f570af4819..0696cb4a3a 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3662,15 +3662,12 @@ void Codegen::handleTryCatch(TryStatement *ast) { Q_ASSERT(ast); RegisterScope scope(this); - BytecodeGenerator::Label noException = bytecodeGenerator->newLabel(); { ControlFlowCatch catchFlow(this, ast->catchExpression); RegisterScope scope(this); TailCallBlocker blockTailCalls(this); // IMPORTANT: destruction will unblock tail calls before catch is generated statement(ast->statement); - bytecodeGenerator->jump().link(noException); } - noException.link(); } void Codegen::handleTryFinally(TryStatement *ast) diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index ed5060a77d..cf7bf3d8ba 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -38,14 +38,21 @@ built-ins/Array/prototype/concat/S15.4.4.4_A3_T1.js fails built-ins/Array/prototype/concat/S15.4.4.4_A3_T2.js fails built-ins/Array/prototype/concat/S15.4.4.4_A3_T3.js fails built-ins/Array/prototype/concat/create-ctor-non-object.js fails +built-ins/Array/prototype/concat/create-ctor-poisoned.js fails built-ins/Array/prototype/concat/create-proxy.js fails +built-ins/Array/prototype/concat/create-species-abrupt.js fails built-ins/Array/prototype/concat/create-species-non-ctor.js fails +built-ins/Array/prototype/concat/create-species-poisoned.js fails built-ins/Array/prototype/concat/create-species.js fails built-ins/Array/prototype/concat/is-concat-spreadable-val-falsey.js fails +built-ins/Array/prototype/copyWithin/return-abrupt-from-has-start.js fails built-ins/Array/prototype/every/15.4.4.16-3-29.js fails built-ins/Array/prototype/filter/create-ctor-non-object.js fails +built-ins/Array/prototype/filter/create-ctor-poisoned.js fails built-ins/Array/prototype/filter/create-proxy.js fails +built-ins/Array/prototype/filter/create-species-abrupt.js fails built-ins/Array/prototype/filter/create-species-non-ctor.js fails +built-ins/Array/prototype/filter/create-species-poisoned.js fails built-ins/Array/prototype/filter/create-species.js fails built-ins/Array/prototype/includes/length-boundaries.js fails built-ins/Array/prototype/indexOf/15.4.4.14-3-28.js fails @@ -53,8 +60,11 @@ built-ins/Array/prototype/indexOf/15.4.4.14-3-29.js fails built-ins/Array/prototype/join/S15.4.4.5_A4_T3.js fails built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-28.js fails built-ins/Array/prototype/map/create-ctor-non-object.js fails +built-ins/Array/prototype/map/create-ctor-poisoned.js fails built-ins/Array/prototype/map/create-proxy.js fails +built-ins/Array/prototype/map/create-species-abrupt.js fails built-ins/Array/prototype/map/create-species-non-ctor.js fails +built-ins/Array/prototype/map/create-species-poisoned.js fails built-ins/Array/prototype/map/create-species.js fails built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js fails built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js fails @@ -69,11 +79,14 @@ built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js f built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js fails built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js fails built-ins/Array/prototype/slice/create-ctor-non-object.js fails +built-ins/Array/prototype/slice/create-ctor-poisoned.js fails built-ins/Array/prototype/slice/create-non-array-invalid-len.js fails built-ins/Array/prototype/slice/create-proxied-array-invalid-len.js fails built-ins/Array/prototype/slice/create-proxy.js fails +built-ins/Array/prototype/slice/create-species-abrupt.js fails built-ins/Array/prototype/slice/create-species-neg-zero.js fails built-ins/Array/prototype/slice/create-species-non-ctor.js fails +built-ins/Array/prototype/slice/create-species-poisoned.js fails built-ins/Array/prototype/slice/create-species.js fails built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js fails built-ins/Array/prototype/slice/length-exceeding-integer-limit.js fails @@ -83,10 +96,13 @@ built-ins/Array/prototype/sort/comparefn-nonfunction-call-throws.js fails built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js fails built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js fails built-ins/Array/prototype/splice/create-ctor-non-object.js fails +built-ins/Array/prototype/splice/create-ctor-poisoned.js fails built-ins/Array/prototype/splice/create-proxy.js fails +built-ins/Array/prototype/splice/create-species-abrupt.js fails built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js fails built-ins/Array/prototype/splice/create-species-neg-zero.js fails built-ins/Array/prototype/splice/create-species-non-ctor.js fails +built-ins/Array/prototype/splice/create-species-poisoned.js fails built-ins/Array/prototype/splice/create-species.js fails built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js fails built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js fails @@ -130,6 +146,7 @@ built-ins/Atomics/wake/wake-negative.js fails built-ins/Atomics/wake/wake-one.js fails built-ins/Atomics/wake/wake-two.js fails built-ins/Atomics/wake/wake-zero.js fails +built-ins/DataView/custom-proto-access-throws.js fails built-ins/DataView/custom-proto-if-object-is-used.js fails built-ins/Date/prototype/toDateString/format.js fails built-ins/Date/prototype/toDateString/invalid-date.js fails @@ -140,8 +157,10 @@ built-ins/Date/prototype/toUTCString/day-names.js fails built-ins/Date/prototype/toUTCString/format.js fails built-ins/Date/prototype/toUTCString/month-names.js fails built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js fails +built-ins/Function/prototype/Symbol.hasInstance/value-get-prototype-of-err.js fails built-ins/Function/prototype/bind/BoundFunction_restricted-properties.js fails built-ins/Function/prototype/bind/instance-name-chained.js fails +built-ins/Function/prototype/bind/instance-name-error.js fails built-ins/Function/prototype/bind/instance-name-non-string.js fails built-ins/Function/prototype/bind/instance-name.js fails built-ins/Function/prototype/toString/AsyncFunction.js fails @@ -156,6 +175,15 @@ built-ins/Function/prototype/toString/async-method-object.js fails built-ins/Function/prototype/toString/method-computed-property-name.js fails built-ins/JSON/parse/revived-proxy-revoked.js fails built-ins/JSON/parse/revived-proxy.js fails +built-ins/JSON/parse/reviver-array-define-prop-err.js fails +built-ins/JSON/parse/reviver-array-delete-err.js fails +built-ins/JSON/parse/reviver-array-length-coerce-err.js fails +built-ins/JSON/parse/reviver-array-length-get-err.js fails +built-ins/JSON/parse/reviver-call-err.js fails +built-ins/JSON/parse/reviver-get-name-err.js fails +built-ins/JSON/parse/reviver-object-define-prop-err.js fails +built-ins/JSON/parse/reviver-object-delete-err.js fails +built-ins/JSON/parse/reviver-object-own-keys-err.js fails built-ins/JSON/stringify/replacer-proxy-revoked.js fails built-ins/JSON/stringify/replacer-proxy.js fails built-ins/JSON/stringify/value-proxy.js fails @@ -179,6 +207,7 @@ built-ins/Object/values/observable-operations.js fails built-ins/Promise/prototype/catch/this-value-obj-coercible.js fails built-ins/Promise/prototype/then/capability-executor-not-callable.js fails built-ins/Promise/prototype/then/ctor-custom.js fails +built-ins/Promise/prototype/then/ctor-throws.js fails built-ins/Promise/race/ctx-ctor.js fails built-ins/Proxy/ownKeys/return-duplicate-entries-throws.js fails built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws.js fails @@ -190,6 +219,7 @@ built-ins/RegExp/prototype/exec/failure-lastindex-access.js fails built-ins/RegExp/prototype/exec/success-lastindex-access.js fails built-ins/RegExp/prototype/source/value-line-terminator.js fails built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js fails +built-ins/RegExp/u180e.js fails built-ins/RegExp/unicode_restricted_brackets.js fails built-ins/RegExp/unicode_restricted_character_class_escape.js fails built-ins/RegExp/unicode_restricted_identity_escape.js fails @@ -198,7 +228,6 @@ built-ins/RegExp/unicode_restricted_identity_escape_c.js fails built-ins/RegExp/unicode_restricted_incomple_quantifier.js fails built-ins/RegExp/unicode_restricted_octal_escape.js fails built-ins/RegExp/unicode_restricted_quantifiable_assertion.js fails -built-ins/RegExp/u180e.js fails built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js fails built-ins/SharedArrayBuffer/data-allocation-after-object-creation.js fails built-ins/SharedArrayBuffer/prototype-from-newtarget.js fails @@ -207,12 +236,15 @@ built-ins/String/prototype/includes/return-abrupt-from-searchstring-regexp-test. built-ins/String/prototype/indexOf/position-tointeger-toprimitive.js fails built-ins/String/prototype/indexOf/position-tointeger.js fails built-ins/String/prototype/indexOf/searchstring-tostring-toprimitive.js fails +built-ins/String/prototype/replace/cstm-replace-get-err.js fails built-ins/String/prototype/replace/cstm-replace-invocation.js fails built-ins/String/prototype/replace/this-value-not-obj-coercible.js fails +built-ins/String/prototype/search/cstm-search-get-err.js fails built-ins/String/prototype/search/cstm-search-invocation.js fails built-ins/String/prototype/search/invoke-builtin-search-searcher-undef.js fails built-ins/String/prototype/search/invoke-builtin-search.js fails built-ins/String/prototype/slice/this-value-not-obj-coercible.js fails +built-ins/String/prototype/split/cstm-split-get-err.js fails built-ins/String/prototype/split/cstm-split-invocation.js fails built-ins/String/prototype/startsWith/return-abrupt-from-searchstring-regexp-test.js fails built-ins/String/prototype/toLocaleLowerCase/Final_Sigma_U180E.js fails @@ -246,14 +278,22 @@ built-ins/TypedArray/prototype/sort/sorted-values-nan.js fails built-ins/TypedArray/prototype/sort/sorted-values.js fails built-ins/TypedArrays/ctors/buffer-arg/defined-negative-length.js fails built-ins/TypedArrays/ctors/object-arg/as-generator-iterable-returns.js fails +built-ins/TypedArrays/ctors/object-arg/iterating-throws.js fails built-ins/TypedArrays/ctors/object-arg/iterator-not-callable-throws.js fails +built-ins/TypedArrays/ctors/object-arg/iterator-throws.js fails built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js fails built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js fails +built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js fails built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js fails built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js fails +built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js fails built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js fails +built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js fails +built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js fails built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js fails built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js fails +built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js fails +built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js fails built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js fails built-ins/TypedArrays/from/arylk-get-length-error.js fails built-ins/TypedArrays/from/arylk-to-length-error.js fails @@ -282,7 +322,7 @@ built-ins/TypedArrays/internals/Get/key-is-not-integer.js fails built-ins/TypedArrays/internals/Get/key-is-not-minus-zero.js fails built-ins/TypedArrays/internals/Get/key-is-out-of-bounds.js fails built-ins/TypedArrays/internals/Set/detached-buffer.js fails -built-ins/TypedArrays/internals/Set/tonumber-value-throws.js strictFails +built-ins/TypedArrays/internals/Set/tonumber-value-throws.js fails built-ins/global/global-object.js fails built-ins/global/property-descriptor.js fails built-ins/isFinite/toprimitive-not-callable-throws.js fails @@ -290,8 +330,8 @@ built-ins/isNaN/toprimitive-not-callable-throws.js fails language/computed-property-names/class/static/method-number.js fails language/computed-property-names/class/static/method-string.js fails language/computed-property-names/class/static/method-symbol.js fails -language/eval-code/direct/new.target.js fails language/eval-code/direct/new.target-arrow.js fails +language/eval-code/direct/new.target.js fails language/eval-code/direct/non-definable-function-with-function.js sloppyFails language/eval-code/direct/non-definable-function-with-variable.js sloppyFails language/eval-code/direct/non-definable-global-function.js sloppyFails @@ -316,6 +356,7 @@ language/eval-code/indirect/non-definable-function-with-function.js sloppyFails language/eval-code/indirect/non-definable-function-with-variable.js sloppyFails language/eval-code/indirect/non-definable-global-function.js fails language/eval-code/indirect/non-definable-global-generator.js fails +language/eval-code/indirect/non-definable-global-var.js strictFails language/eval-code/indirect/super-call.js fails language/eval-code/indirect/super-prop.js fails language/eval-code/indirect/this-value-func.js strictFails -- cgit v1.2.3 From b7b384658b21e741f9a1fde60b1c1ee69a83e278 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 24 Jan 2019 10:37:33 +0100 Subject: Remove revisions from Qt.labs.settings methods and properties Qt.labs plugins should always have revision 1.0 until they graduate. However, keeping registration Qt.labs.location 1.1 to prevent source incompatibilities. Fixes: QTBUG-73239 Change-Id: I01c66c5d3054fb95df54988b7ce6535ccc65d3a6 Reviewed-by: Shawn Rutledge --- src/imports/settings/plugin.cpp | 2 +- src/imports/settings/plugins.qmltypes | 3 --- src/imports/settings/qqmlsettings.cpp | 12 ++++++------ src/imports/settings/qqmlsettings_p.h | 6 +++--- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index 3ac0ad4653..eb7d5027a4 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -55,7 +55,7 @@ public: { Q_ASSERT(QByteArray(uri) == QByteArray("Qt.labs.settings")); qmlRegisterType(uri, 1, 0, "Settings"); - qmlRegisterType(uri, 1, 1, "Settings"); + qmlRegisterModule(uri, 1, 1); // QTBUG-73239 } }; diff --git a/src/imports/settings/plugins.qmltypes b/src/imports/settings/plugins.qmltypes index 1d69fcf7e9..3c9685fe10 100644 --- a/src/imports/settings/plugins.qmltypes +++ b/src/imports/settings/plugins.qmltypes @@ -20,20 +20,17 @@ Module { Property { name: "fileName"; revision: 1; type: "string" } Method { name: "value" - revision: 1 type: "QVariant" Parameter { name: "key"; type: "string" } Parameter { name: "defaultValue"; type: "QVariant" } } Method { name: "value" - revision: 1 type: "QVariant" Parameter { name: "key"; type: "string" } } Method { name: "setValue" - revision: 1 Parameter { name: "key"; type: "string" } Parameter { name: "value"; type: "QVariant" } } diff --git a/src/imports/settings/qqmlsettings.cpp b/src/imports/settings/qqmlsettings.cpp index 310ef62d9f..f7a7d8b055 100644 --- a/src/imports/settings/qqmlsettings.cpp +++ b/src/imports/settings/qqmlsettings.cpp @@ -433,9 +433,9 @@ void QQmlSettings::setCategory(const QString &category) This property holds the path to the settings file. If the file doesn't already exist, it is created. - \sa QSettings::fileName, QSettings::IniFormat + \since Qt 5.12 - \since Qt.labs.settings 1.1 + \sa QSettings::fileName, QSettings::IniFormat */ QString QQmlSettings::fileName() const { @@ -460,9 +460,9 @@ void QQmlSettings::setFileName(const QString &fileName) Returns the value for setting \a key. If the setting doesn't exist, returns \a defaultValue. - \sa QSettings::value + \since Qt 5.12 - \since Qt.labs.settings 1.1 + \sa QSettings::value */ QVariant QQmlSettings::value(const QString &key, const QVariant &defaultValue) const { @@ -476,9 +476,9 @@ QVariant QQmlSettings::value(const QString &key, const QVariant &defaultValue) c Sets the value of setting key to value. If the key already exists, the previous value is overwritten. - \sa QSettings::setValue + \since Qt 5.12 - \since Qt.labs.settings 1.1 + \sa QSettings::setValue */ void QQmlSettings::setValue(const QString &key, const QVariant &value) { diff --git a/src/imports/settings/qqmlsettings_p.h b/src/imports/settings/qqmlsettings_p.h index f73e595557..f9122a58f7 100644 --- a/src/imports/settings/qqmlsettings_p.h +++ b/src/imports/settings/qqmlsettings_p.h @@ -65,7 +65,7 @@ class QQmlSettings : public QObject, public QQmlParserStatus Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QString category READ category WRITE setCategory FINAL) - Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL REVISION 1) + Q_PROPERTY(QString fileName READ fileName WRITE setFileName FINAL) public: explicit QQmlSettings(QObject *parent = 0); @@ -77,8 +77,8 @@ public: QString fileName() const; void setFileName(const QString &fileName); - Q_REVISION(1) Q_INVOKABLE QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; - Q_REVISION(1) Q_INVOKABLE void setValue(const QString &key, const QVariant &value); + Q_INVOKABLE QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; + Q_INVOKABLE void setValue(const QString &key, const QVariant &value); protected: void timerEvent(QTimerEvent *event) override; -- cgit v1.2.3 From a8729cf143a79b274c002166476c54dc152c6679 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 19 Nov 2018 16:22:45 +0100 Subject: TapHander: do not "want" an eventPoint that is outside parent bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far it was checking parentContains() on press, release, or when the gesturePolicy is WithinBounds, but not for each movement when the policy is DragThreshold (the default). This might explain most of the remaining warning noise: "pointId is missing from current event, but was neither canceled nor released" because it was possible for TapHandler to remember wanting a point that it should not have wanted, but without taking any kind of grab, and then complaining when that point was no longer present. Since it did not grab, it did not get the release, unless the release was part of an event containing a point that it DID grab. Fixes: QTBUG-71887 Change-Id: I26ce62279574cf6b0150f24e486f224a604ac6b1 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquicktaphandler.cpp | 2 +- src/quick/items/qquickevents.cpp | 2 +- .../pointerhandlers/flickableinterop/tst_flickableinterop.cpp | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index c1658ec5d2..9386676b7a 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -129,7 +129,7 @@ bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point) case QQuickEventPoint::Updated: switch (m_gesturePolicy) { case DragThreshold: - ret = !overThreshold; + ret = !overThreshold && parentContains(point); break; case WithinBounds: ret = parentContains(point); diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 31c56b7cb7..2eaab164a0 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -851,7 +851,7 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber)) return; if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { - qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) + qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) << "@" << m_scenePos << ": grab" << m_exclusiveGrabber << "->" << grabber; } QQuickItem *oldGrabberItem = grabberItem(); diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index e73588bdef..cf2ac4a830 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -301,7 +301,7 @@ void tst_FlickableInterop::touchDragSlider() // Drag the slider in the allowed (vertical) direction tappedSpy.clear(); - QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint(); + QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint() - QPoint(0, 8); QTest::touchEvent(window, touchDevice).press(1, p1, window); QQuickTouchUtils::flush(window); QTRY_VERIFY(slider->property("pressed").toBool()); @@ -343,12 +343,12 @@ void tst_FlickableInterop::mouseDragSlider_data() QTest::addColumn("expectedDragHandlerActive"); QTest::addColumn("expectedFlickableMoving"); - QTest::newRow("drag down on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false; + QTest::newRow("drag down on knob of knobSlider") << "knobSlider" << QPoint(0, -8) << QPoint(0, 1) << true << true << false; QTest::newRow("drag sideways on knob of knobSlider") << "knobSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true; QTest::newRow("drag down on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(0, 1) << false << false << true; QTest::newRow("drag sideways on groove of knobSlider") << "knobSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true; - QTest::newRow("drag down on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(0, 1) << true << true << false; + QTest::newRow("drag down on knob of grooveSlider") << "grooveSlider" << QPoint(0, -8) << QPoint(0, 1) << true << true << false; QTest::newRow("drag sideways on knob of grooveSlider") << "grooveSlider" << QPoint(0, 0) << QPoint(1, 0) << true << false << true; QTest::newRow("drag down on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(0, 1) << false << true << false; QTest::newRow("drag sideways on groove of grooveSlider") << "grooveSlider" << QPoint(0, 20) << QPoint(1, 0) << false << false << true; @@ -391,6 +391,10 @@ void tst_FlickableInterop::mouseDragSlider() QCOMPARE(slider->property("value").toInt(), 49); p1 += dragDirection; // one more pixel QTest::mouseMove(window, p1); + // After moving by the drag threshold, the point should still be inside the knob. + // However, QQuickTapHandler::wantsEventPoint() returns false because the drag threshold is exceeded. + // Therefore QQuickTapHandler::setPressed(false, true, point) is called: the active state is canceled. + QCOMPARE(slider->property("pressed").toBool(), false); QCOMPARE(drag->active(), expectedDragHandlerActive); // drag farther, to make sure the knob gets adjusted significantly p1 += QPoint(10 * dragDirection.x(), 10 * dragDirection.y()); -- cgit v1.2.3 From 205f836e5d976a983638dd2969077a9e24c1c4fd Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 25 Jan 2019 14:18:30 +0100 Subject: V4: Fix unwind handler reset after for-in loop Consider this JavaScript snippet: function f() { for (var i in []) {} } This generates the following bytecode sequence: 2 0: 14 00 09 MoveConst r3, C0 3: ec 00 00 DefineArray (function), 0 6: da 00 GetIterator 0 8: 18 08 StoreReg r2 10: c0 0f SetUnwindHandler 27 12: 50 04 Jump 18 14: 16 0a LoadReg r4 16: 18 07 StoreReg r1 3 18: 16 08 LoadReg r2 20: dc 0a 09 IteratorNext r4, r3 23: 54 f5 JumpFalse 14 25: 50 03 Jump 30 27: c0 00 SetUnwindHandler 29: c2 UnwindDispatch 4 30: 0e LoadUndefined 31: 02 Ret The problem is a normal loop exit: instruction 23 will not jump back, but fall through, and then instruction 25 will jump over the instructions resetting the unwind handler (27 + 29). Removing this jump fixes the issue. Change-Id: Ic9f03555ebebc27144490bce04e9a4166ed7c97c Reviewed-by: Ulf Hermann --- src/qml/compiler/qv4codegen.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 0696cb4a3a..fb3c66b123 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3339,7 +3339,6 @@ bool Codegen::visit(ForEachStatement *ast) BytecodeGenerator::Label in = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); - BytecodeGenerator::Label done = bytecodeGenerator->newLabel(); { auto cleanup = [ast, iterator, iteratorDone, this]() { @@ -3397,13 +3396,11 @@ bool Codegen::visit(ForEachStatement *ast) next.done = iteratorDone.stackSlot(); bytecodeGenerator->addInstruction(next); bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body); - bytecodeGenerator->jump().link(done); - end.link(); + // all execution paths need to end up here (normal loop exit, break, and exceptions) in + // order to reset the unwind handler, and to close the iterator in calse of an for-of loop. } - done.link(); - return false; } -- cgit v1.2.3 From 5d8d0d7068bc8498ea2a6a4c9bc16e0eeb92836c Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Thu, 31 Jan 2019 15:24:46 +0100 Subject: doc: Two class members can not have the same name At least gcc complains about it. Change-Id: I122b0bab2c2fcea24814a83f005be1ad4686aa78 Reviewed-by: Simon Hausmann --- src/qml/doc/src/cppintegration/definetypes.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index 7f3ff416a1..0cce1895cb 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -691,7 +691,7 @@ public: QQmlListProperty messages(); private: - QList messages; + QList m_messages; }; \endcode -- cgit v1.2.3