diff options
author | Andre de la Rocha <andre.rocha@qt.io> | 2019-08-30 20:02:58 +0200 |
---|---|---|
committer | Andre de la Rocha <andre.rocha@qt.io> | 2019-09-02 13:53:56 +0200 |
commit | 1c55a6caf1fc2b8a73a9a756bcf6894c5d4e4398 (patch) | |
tree | e36947565b20f9870a40456e4d1243a9580e98ab /src/plugins/platforms/windows/uiautomation | |
parent | 364b9c80de069ff2c5970d0a9591c00c71e871cf (diff) |
Windows QPA: Fix crash in UI Automation with Youdao Dictionary
Unlike other accessibility classes, QAccessibleTree is returning a
different instance, with a different ID, every time child()/childAt()
are called for the same child elements. This causes
ElementProviderFromPoint to return different IRawElementProviderSimple
instances every time, for the same coordinates, which causes the
NetEase Youdao Dictionary to call it in an infinite loop, allocating
new QAccessibleTableCell instances, until the application crashes.
The crash happened, for instance, just by using the mouse over
Qt Creator's project tree while Youdao Dictionary was running. While
the root cause seems to be QAccessibleTree not caching and reusing
objects, this change adds a layer of safety to the UI Automation
classes in the Windows QPA, to avoid causing a crash until
QAccessibleTree, and possibly other accessibility classes, are fixed.
Fixes: QTBUG-77974
Change-Id: I9b0c8174bc0fd9ef7f5626ee0b72c8a9626520ee
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src/plugins/platforms/windows/uiautomation')
-rw-r--r-- | src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index a427e553f0..5a05adbf81 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -670,18 +670,26 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR QPoint point; nativeUiaPointToPoint(uiaPoint, window, &point); - QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y()); - - if (targetacc) { - QAccessibleInterface *acc = targetacc; - // Controls can be embedded within grouping elements. By default returns the innermost control. - while (acc) { - targetacc = acc; - // For accessibility tools it may be better to return the text element instead of its subcomponents. - if (targetacc->textInterface()) break; - acc = acc->childAt(point.x(), point.y()); + if (auto targetacc = accessible->childAt(point.x(), point.y())) { + auto acc = accessible->childAt(point.x(), point.y()); + // Reject the cases where childAt() returns a different instance in each call for the same + // element (e.g., QAccessibleTree), as it causes an endless loop with Youdao Dictionary installed. + if (targetacc == acc) { + // Controls can be embedded within grouping elements. By default returns the innermost control. + while (acc) { + targetacc = acc; + // For accessibility tools it may be better to return the text element instead of its subcomponents. + if (targetacc->textInterface()) break; + acc = targetacc->childAt(point.x(), point.y()); + if (acc != targetacc->childAt(point.x(), point.y())) { + qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << targetacc; + break; + } + } + *pRetVal = providerForAccessible(targetacc); + } else { + qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << accessible; } - *pRetVal = providerForAccessible(targetacc); } return S_OK; } |