diff options
author | Patrick Luby <plubius@neooffice.org> | 2023-06-15 17:10:17 -0400 |
---|---|---|
committer | Patrick Luby <plubius@neooffice.org> | 2023-06-16 18:38:55 +0200 |
commit | b6299c9e56f70ebc124814f4001e149e7be298ad (patch) | |
tree | 5d454a42e4e839e46009287bd060476162c0b40b | |
parent | 52c34f4e84c5125e2a3c72b57a3c4d30a593debd (diff) |
tdf#146626 catch IndexOutOfBoundsException when fetching accessible children
com::sun::star::accessibility::XAccessibleContext::getAccessibleChild()
can throw an IndexOutOfBoundsException exception even when fetching with
an index that is positive and less than the value returned by a call to
the accessible context's getAccessibleChildCount() method so put every
getAccessibleChild() call in a try/catch block.
Note: this is actually expected behavior even though it is rare. For
example, accessibility::AccessibleTextHelper_Impl::getAccessibleChild()
uses the following code snippet to throw such an exception:
if( 0 > i || i >= getAccessibleChildCount() ||
GetTextForwarder().GetParagraphCount() <= i )
In the case of tdf#146626, getAccessibleChildCount() returns 22 but
getAccessibleChild(1) throws such an exception due to the last
condition in the above code snippet.
Change-Id: If974afb7b9178faa99b91dcd79eb5f169bbfe13e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153160
Tested-by: Jenkins
Reviewed-by: Patrick Luby <plubius@neooffice.org>
-rw-r--r-- | vcl/osx/a11yfocustracker.cxx | 30 | ||||
-rw-r--r-- | vcl/osx/a11yrolehelper.mm | 26 | ||||
-rw-r--r-- | vcl/osx/a11ywrapper.mm | 47 | ||||
-rw-r--r-- | vcl/osx/documentfocuslistener.cxx | 44 |
4 files changed, 101 insertions, 46 deletions
diff --git a/vcl/osx/a11yfocustracker.cxx b/vcl/osx/a11yfocustracker.cxx index 8d830cdb62a1..2aaa8b0a8e25 100644 --- a/vcl/osx/a11yfocustracker.cxx +++ b/vcl/osx/a11yfocustracker.cxx @@ -30,8 +30,10 @@ #include <com/sun/star/accessibility/XAccessibleSelection.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::lang; using namespace ::com::sun::star::uno; AquaA11yFocusTracker& TheAquaA11yFocusTracker() @@ -118,10 +120,16 @@ void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox) if( xContext.is() ) { - ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() ); - if( nPos != ToolBox::ITEM_NOTFOUND ) - setFocusedObject( xContext->getAccessibleChild( nPos ) ); - //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32! + try { + ToolBox::ImplToolItems::size_type nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() ); + if( nPos != ToolBox::ITEM_NOTFOUND ) + setFocusedObject( xContext->getAccessibleChild( nPos ) ); + //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32! + } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "Accessible object has invalid index in parent"); + } } } } @@ -150,11 +158,17 @@ void AquaA11yFocusTracker::toolbox_open_floater(vcl::Window *pWindow) return; } if ( rxContext -> getAccessibleChildCount() > 0 ) { - Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 ); - if ( ! rxAccessibleChild.is() ) { - return; + try { + Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 ); + if ( ! rxAccessibleChild.is() ) { + return; + } + setFocusedObject ( rxAccessibleChild ); + } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "No valid accessible objects in parent"); } - setFocusedObject ( rxAccessibleChild ); } } } diff --git a/vcl/osx/a11yrolehelper.mm b/vcl/osx/a11yrolehelper.mm index 5cb75c94a86f..e95036dbebd9 100644 --- a/vcl/osx/a11yrolehelper.mm +++ b/vcl/osx/a11yrolehelper.mm @@ -24,8 +24,12 @@ #include <com/sun/star/accessibility/AccessibleRole.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +#include <sal/log.hxx> using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::lang; using namespace ::com::sun::star::uno; @implementation AquaA11yRoleHelper @@ -153,17 +157,23 @@ using namespace ::com::sun::star::uno; } } } else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { - Reference < XAccessible > rxAccessible = accessibleContext -> getAccessibleChild(0); - if ( rxAccessible.is() ) { - Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); - if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) { - sal_Int64 nStateSet = rxAccessibleContext -> getAccessibleStateSet(); - if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) { - [ nativeRole release ]; - nativeRole = NSAccessibilityPopUpButtonRole; + try { + Reference < XAccessible > rxAccessible = accessibleContext -> getAccessibleChild(0); + if ( rxAccessible.is() ) { + Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); + if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) { + sal_Int64 nStateSet = rxAccessibleContext -> getAccessibleStateSet(); + if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) { + [ nativeRole release ]; + nativeRole = NSAccessibilityPopUpButtonRole; + } } } } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "No valid accessible objects in parent"); + } } return nativeRole; } diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm index 06967df5aa3e..0ca256a7552f 100644 --- a/vcl/osx/a11ywrapper.mm +++ b/vcl/osx/a11ywrapper.mm @@ -45,6 +45,7 @@ #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp> #include <com/sun/star/accessibility/AccessibleRelationType.hpp> #include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> #include <sal/log.hxx> #include <osl/diagnose.h> @@ -339,19 +340,25 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; Reference< XAccessibleContext > xContext( [ self accessibleContext ] ); - sal_Int64 cnt = xContext -> getAccessibleChildCount(); - for ( sal_Int64 i = 0; i < cnt; i++ ) { - Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) ); - if( xChild.is() ) { - Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() ); - // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here - if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) { - id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ]; - [ children addObject: wrapper ]; - [ wrapper release ]; + try { + sal_Int64 cnt = xContext -> getAccessibleChildCount(); + for ( sal_Int64 i = 0; i < cnt; i++ ) { + Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) ); + if( xChild.is() ) { + Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() ); + // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here + if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) { + id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ]; + [ children addObject: wrapper ]; + [ wrapper release ]; + } } } } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "Accessible object has invalid index in parent"); + } // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons if ( ! mActsAsRadioGroup ) { @@ -1063,16 +1070,22 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, } if( bSafeToIterate ) { - for ( sal_Int64 i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { - Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); - if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { - Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); - if ( myHitChild.is() ) { - hitChild = myHitChild; - break; + try { + for ( sal_Int64 i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { + Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); + if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { + Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); + if ( myHitChild.is() ) { + hitChild = myHitChild; + break; + } } } } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "Accessible object has invalid index in parent"); + } } } } catch ( RuntimeException ) { diff --git a/vcl/osx/documentfocuslistener.cxx b/vcl/osx/documentfocuslistener.cxx index 5f39e7cbfdc0..44a3506f860d 100644 --- a/vcl/osx/documentfocuslistener.cxx +++ b/vcl/osx/documentfocuslistener.cxx @@ -106,7 +106,13 @@ Reference< XAccessible > DocumentFocusListener::getAccessible(const EventObject& Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); if( xParentContext.is() ) { - return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() ); + try { + return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() ); + } + catch (const IndexOutOfBoundsException&) + { + SAL_WARN("vcl", "Accessible object has invalid index in parent"); + } } } } @@ -153,13 +159,19 @@ void DocumentFocusListener::attachRecursive( if( ! (nStateSet & AccessibleStateType::MANAGES_DESCENDANTS) ) { - sal_Int64 n, nmax = xContext->getAccessibleChildCount(); - for( n = 0; n < nmax; n++ ) + try { + sal_Int64 n, nmax = xContext->getAccessibleChildCount(); + for( n = 0; n < nmax; n++ ) + { + Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); + + if( xChild.is() ) + attachRecursive(xChild); + } + } + catch (const IndexOutOfBoundsException&) { - Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); - - if( xChild.is() ) - attachRecursive(xChild); + SAL_WARN("vcl", "Accessible object index does not exist in parent"); } } } @@ -197,13 +209,19 @@ void DocumentFocusListener::detachRecursive( if( ! (nStateSet & AccessibleStateType::MANAGES_DESCENDANTS) ) { - sal_Int64 n, nmax = xContext->getAccessibleChildCount(); - for( n = 0; n < nmax; n++ ) + try { + sal_Int64 n, nmax = xContext->getAccessibleChildCount(); + for( n = 0; n < nmax; n++ ) + { + Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); + + if( xChild.is() ) + detachRecursive(xChild); + } + } + catch (const IndexOutOfBoundsException&) { - Reference< XAccessible > xChild( xContext->getAccessibleChild( n ) ); - - if( xChild.is() ) - detachRecursive(xChild); + SAL_WARN("vcl", "Accessible object index does not exist in parent"); } } } |